home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / raytrace / pov / bin / xtras / ibm.c < prev    next >
Text File  |  1994-09-11  |  106KB  |  3,240 lines

  1. /****************************************************************************
  2. *
  3. *  ATTENTION!!!
  4. *
  5. *  THIS FILE HAS BEEN MODIFIED!!! IT IS NOT PART OF THE OFFICAL
  6. *  POV-RAY 2.2 DISTRIBUTION!!!
  7. *
  8. *  THIS FILE IS PART OF "FASTER THAN POV-RAY" (VERSION 2.2),
  9. *  A SPED-UP VERSION OF POV-RAY 2.2. USE AT YOUR OWN RISK!!!!!!
  10. *
  11. *  New files: addon0.c, addon1.c, addon2.c, addon3.c, addon.h
  12. *
  13. *  The additional modules were written by Dieter Bayer.
  14. *
  15. *  Send comments, suggestions, bugs, ideas ... to:
  16. *
  17. *  e-mail: dieter@cip.e-technik.uni-erlangen.de
  18. *  CIS: 100255.3074
  19. *
  20. *  All changed/added lines are enclosed in #ifdef DB_CODE ... #endif
  21. *
  22. *  The vista projection was taken from:
  23. *
  24. *    A. Hashimoto, T. Akimoto, K. Mase, and Y. Suenaga, 
  25. *    "Vista Ray-Tracing: High Speed Ray Tracing Using Perspective
  26. *    Projection Image", New Advances in Computer Graphics, Proceedings
  27. *    of CG International '89, R. A. Earnshaw, B. Wyvill (Eds.), 
  28. *    Springer, ..., pp. 549-560
  29. *
  30. *  The idea for the light buffer was taken from:
  31. *
  32. *    E. Haines and D. Greenberg, "The Light Buffer: A Shadow-Testing 
  33. *    Accelerator", IEEE CG&A, Vol. 6, No. 9, Sept. 1986, pp. 6-16
  34. *
  35. *****************************************************************************/
  36.  
  37. /****************************************************************************
  38. *            ibm.c
  39. *
  40. *  This module implements the IBM-PC specific routines for POV-Ray.
  41. *
  42. *  from Persistence of Vision Raytracer
  43. *  Copyright 1993 Persistence of Vision Team
  44. *---------------------------------------------------------------------------
  45. *  NOTICE: This source code file is provided so that users may experiment
  46. *  with enhancements to POV-Ray and to port the software to platforms other
  47. *  than those supported by the POV-Ray Team.  There are strict rules under
  48. *  which you are permitted to use this file.  The rules are in the file
  49. *  named POVLEGAL.DOC which should be distributed with this file. If
  50. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  51. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  52. *  Forum.  The latest version of POV-Ray may be found there as well.
  53. *
  54. * This program is based on the popular DKB raytracer version 2.12.
  55. * DKBTrace was originally written by David K. Buck.
  56. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  57. *
  58. *****************************************************************************/
  59.  
  60. /* Original IBM VGA "colour" output routines for MS/DOS by Aaron A. Collins.
  61.  
  62.    This will deliver approximate colorings using HSV values for the selection.
  63.    The palette map is divided into 4 parts - upper and lower half generated
  64.    with full and half "value" (intensity), respectively.  These halves are
  65.    further halved by full and half saturation values of each range (pastels).
  66.    There are three constant colors, black, white, and grey.  They are used
  67.    when the saturation is low enough that the hue becomes undefined, and which
  68.    one is selected is based on a simple range map of "value".  Usage of the
  69.    palette is accomplished by converting the requested color RGB into an HSV
  70.    value.  If the saturation is too low (< .25) then black, white or grey is
  71.    selected.  If there is enough saturation to consider looking at the hue,
  72.    then the hue range of 1-63 is scaled into one of the 4 palette quadrants
  73.    based on its "value" and "saturation" characteristics.
  74.  
  75.    Further SVGA, MVGA mods by Aaron A. Collins:
  76.    SVGA, MVGA assembler routines originally by John Bridges.
  77.    VESA assembler routines from FRACTINT, by The Stone Soup Group
  78.    AT&T VDC600 SVGA mods to DKB Trace 2.01 module IBM.C by John Gooding
  79.  
  80.    This file now represents the collective wisdom of the VGAKIT34 package,
  81.    with support for all of the SVGA types known to mankind.  Seriously,
  82.    VGAKIT34 is an excellent technical reference for IBM programmers wishing
  83.    to do any sort of SVGA video access, and it encompasses nearly all of the
  84.    SVGA adapters in use today.    It was written by John Bridges, a.k.a.
  85.    CIS:73307,606, GENIE:J.BRIDGES.  It was originally coded in IBM 80x86
  86.    assembler, and since DKBTrace is a completely "C"-based package, I have
  87.    converted John's assembler routines all into "C".  These may be a tad bit
  88.    slower, but they should be compatible across a wide variety of 80x86/(S)VGA
  89.    machines.  Note if you have a regular cheapo VGA card like myself, included
  90.    is "MODE13x" or MVGA (modified VGA) mode (some call it "tweaked", but I
  91.    call it "Simulated SVGA"), which gives 360x480 on any reasonably register-
  92.    compatible plain vanilla VGA card.  This mode gives a good simulated 640 by
  93.    480 screen resolution.  I did not implement all the neat hi-res modes of
  94.    all the various SVGA adapters, if you select a trace size bigger than the
  95.    program and/or card can handle (most likely 640x480), it is dynamically
  96.    scaled to fit the available resolution, so you'll be able to see a rough
  97.    approximation of an 800x600 trace even on any el-cheapo VGA card at 320x200
  98.    resolution.    The VESA VGA mode was freely adapted from FRACTINT, whose GIF
  99.    reading routines we are already using in DKBTrace.  I hope my conversion
  100.    of it works properly.
  101.  
  102.    There is still a reported problem with the EVEREX autodetect returning
  103.    TRIDENT.  In fact EVEREX uses a TRIDENT chip set, but apparently there
  104.    is some difference in operation.  There are cryptic diagnostic messages
  105.    such as T0000, etc. printed as a result of the autodetection routines
  106.    to help track down why the error is happening.  If you are experiencing
  107.    problems with EVEREX or TRIDENT, make note of the letter-4 digit code you
  108.    are given.  There is now an autodetect for VDC600 that I hope will work
  109.    universally.  A similar problem as the EVEREX exists, in that the VDC600
  110.    is detected as a PARADISE because it uses the PARADISE chip set.  I am now
  111.    looking for what I believe to be the model number in the BIOS ROM of the
  112.    VDC600 to differentiate between the two.  I hope this works    with all
  113.    VDC600's, as I only had one example to work from.  Please send all bug
  114.    reports to Aaron Collins at the "You Can Call Me RAY" BBS, the number is
  115.    in the authors.txt document.
  116.  
  117.  
  118.    POV-Ray Enhancements:
  119.  
  120.    (S)VGA B&W 64 Greyscale code courtesy of Grant Hess 6/21/91
  121.  
  122.    16/24-bit HGWS/TIGA/TRUECOLOR code courtesy of Jay S. Curtis 11/15/90
  123.  
  124.    VGA "332" palette routines courtesy of Alexander Enzmann 7/20/91
  125.  
  126.    Additional support for VESA and Tseng Labs 256 and 32768 color modes by
  127.    Charles Marslett  (CIS: 75300,1636).  Resolution is selected to be the
  128.    lowest possible and still fit the image entirely on the screen. 4/28/91
  129.  
  130.    ATI VGA Wonder XL Support for 32,768 color mode and all other SVGA modes
  131.    by Randy Antler.  Also image centering, outline box, and forces SVGA mode
  132.    for small images.  Minor bug fixes and cleanups as well. 9/11/91
  133.  
  134.    Combined IBMPRO.C and IBM.C into 1 file.
  135.    B.Pulver 10/20/91
  136.  
  137.    Corrected defects in the centering and high color support for VESA modes
  138.    (particularly necessary for the newer 24-bit color cards and S3 based
  139.    Windows accellerator cards) -- Charles Marslett, 12/8/91 to 4/25/92.
  140.  
  141.    Extended Doug's dithering code to other high color modes and eliminated
  142.    a bad validity check in the 24-bit code high color cards.  Had to add
  143.    an "#include <float.h>" to ibmconf.h for the WATCOM C compilers with the
  144.    patchlevel C include files -- Charles Marslett, 10/4/92.
  145.  
  146.    Added support for Diamond Speedstar 24X. Uses a modified copy of some
  147.    of the Paradise code. There is no AutoDetect functionality for this
  148.    card, though.  Note that a couple of pixels (about 14), namely those
  149.    that straddle bank boundaries will be displayed incorrectly.
  150.                  -- Lutz Kretzschmar,  10/30/92
  151.  
  152.    Fixed (obvious) bug for displaying images larger than screen
  153.    resolutions. Strange no-one caught it, it didn't work!. The line coord
  154.    cache is set to the max value by the box() function. Added code to
  155.    reset the values inside box().
  156.    Added bank switch checking inside pixels for truecolor modes.
  157.    Added HiColor display in 640x480 and 800x600 resolutions for Diamond
  158.    SpeedStar 24X.       -- Lutz Kretzschmar,  11/05/92
  159.  
  160.    Added TARGA+ display adapter support and reworked find_go32() to make
  161.    the VESA and TARGA routines work properly with DJ's port of IBMGCC
  162.    - Aaron A. Collins, 2/2/93.
  163.  
  164.    Completed Intel Code Builder code for VESA 1.2 support. - B.Pulver 2/15/93
  165.    Added: Set palette to P_332 if Hi/True color VESA init fails.
  166.       Doubled dithering matrixes to support 2048Xxxxx images.
  167.       Added code to disable dithering @ rez over 2048Xxxxx.
  168.       Added message warning user of failure if no_valid_mode is called
  169.       during VESA initialization attempt. - B.Pulver 5/13/93
  170.  
  171.    Found consistency bug in previously fixed find_go32(), so this too
  172.    has been fixed.  Found DJGCC's setvbuf() was blowing up the VESA/TARGA
  173.    "answer" area (in low real mode accessable mem) after a disk write, so
  174.    the setvbuf() function has been dummied up in this file to do nothing.
  175.    Added some DEBUG_VIDEO diagnostics for figuring out problems running a
  176.    TARGA+ display on the Intel Code Builder. - Aaron A. Collins, 8/2/1993
  177.  
  178.    Updated Watcom VESA support for DPMI. -- Carl Peterson 1/94
  179.  
  180.    Added support for Paradise true color cards (option PARADISE) :
  181.    FULL color (32000+) and true color modes. The code for full color modes
  182.    is exactly the same as the one for the Diamond 24X, but not the code for
  183.    the true color mode. Did not add support for 800x600 and 1024x768 modes
  184.    with 256 colors, please use the VESA option for these modes.
  185.    Fixed bug with autodetect video modes and vesa modes with DJGCC
  186.    (deleted find_go32() and used the _go32_dpmi_simulate_dos_int() with
  187.    _go32_linear_address_of_transfer_buffer).  Emmanuel Anne, 30/8/1994.
  188. */
  189.  
  190. #define DITHERED    /* Defined to test Doug Muir's dithering code */
  191.  
  192. /*#define DEBUG_VIDEO*/ /* Uncomment to display Video initialization info during program startup. */
  193. /*#define SVBOK*/    /* Uncomment to use setvbuf in GCCDOS anyway. */
  194.  
  195. #ifdef DEBUG_VIDEO
  196. int diaged;        /* excessive diagnostic message clamp */
  197. #endif
  198.  
  199. #include <dos.h>    /* MS-DOS specific - for int86() REGS struct, etc. */
  200. #include <stdarg.h>
  201. #include <time.h>
  202. #include "frame.h"
  203. #include "povproto.h"
  204.  
  205. #if !defined(DOS386) && !defined(_INTELC32_) && !defined(__386__) && !defined(GCCDOS)
  206.   #include "tiga.h"       /* HGWS/TIGA function library include files - not supported by 32 bit compilers */
  207.   #include "tigadefs.h"
  208.   #include "extend.h"
  209. #endif
  210.  
  211. #include <io.h>       /* for low-level open() funct, etc. */
  212. #include <fcntl.h>      /* for low-level open() modes O_RDWR, O_BINARY, etc. */
  213.  
  214. /* Compiler specific setups & defines. */
  215. #ifdef __TURBOC__
  216.   extern unsigned _stklen = 12288; /* fairly large stack for HEAVY recursion */
  217.   #define CLD asm cld
  218.   #define _asm asm
  219.   #define _far far
  220. #else
  221. #ifdef __WATCOMC__
  222.   #include <float.h>
  223.   #define CLD clear_direction()
  224.   unsigned short __8087cw = IC_AFFINE | RC_NEAR | PC_64  | 0x007F;
  225.   void clear_direction(void);
  226.   #pragma aux clear_direction = 0xFC parm [] modify nomemory;
  227. /* CCP - Added following defintions */
  228. #ifdef __386__
  229. typedef unsigned long DWORD;
  230.  
  231. #define D32RealSeg(P)    ((((DWORD) (P)) >> 4) & 0xFFFF)
  232. #define D32RealOff(P)    (((DWORD) (P)) & 0xF)
  233.  
  234. static struct rminfo {        /* DPMI Real Mode Call structure */
  235.     long EDI;
  236.     long ESI;
  237.     long EBP;
  238.     long reserved_by_system;
  239.     long EBX;
  240.     long EDX;
  241.     long ECX;
  242.     long EAX;
  243.     short flags;
  244.     short ES,DS,FS,GS,IP,CS,SP,SS;
  245. } RMI;
  246. /* CCP - End */
  247.  
  248.   #define ax eax
  249.   #define bx ebx
  250.   #define cx ecx
  251.   #define dx edx
  252.   #define di edi
  253.   #define int86 int386
  254.   #define int86x int386x
  255. #endif
  256. #else
  257.  
  258. #ifdef _INTELC32_
  259.   #pragma interrupt (int10)   /* Need to install user INT10 handler for VESA. */
  260.   /* Use MSC 6.0a compatible mode. NOANSI switch in Makefile */
  261.   #include <stk.h>          /* Stack support for user INT10. */
  262.   #define CLD cld()
  263.  
  264.   void int10();
  265.   void (*prev_int10)();
  266.  
  267.   void cld (void)          /* Clear direction flag. */
  268.   {
  269.     unsigned int flags;
  270.     flags = _getflags();
  271.     flags = flags & (!_FLAG_DIRECTION);
  272.     _setflags (flags);
  273.   }
  274. #else
  275. #ifdef __ZTC__
  276.   #include <math.h>
  277.   #include <int.h>
  278.  
  279.   #ifndef DOS386
  280.   #ifndef DOS16RM
  281.   unsigned _stack = 12288;
  282.   #endif
  283.   #endif
  284.  
  285.   #define CLD
  286.   #ifndef min
  287.   #define min(x,y) ((x) < (y)? (x): (y))
  288.   #endif
  289.  
  290.   #ifdef DOS386
  291.     extern unsigned short _x386_zero_base_selector;
  292.     #define _disable()
  293.     #define _enable()
  294.     #define _cdecl
  295.   #else
  296.   #ifdef DOS16RM
  297.     void *D16SegAbsolute(long absadr, short size);
  298.     void D16SegCancel(void *segptr);
  299.     #define _disable()
  300.     #define _enable()
  301.     unsigned char *display_base;
  302.   #else
  303.     #define _disable() int_off()
  304.     #define _enable()  int_on()
  305.   #endif
  306.   #endif
  307.  
  308. #else
  309. #ifdef GCCDOS
  310.   #include <errno.h>
  311.   #include <pc.h>
  312.   #include <ctype.h>
  313.   #include <go32.h>
  314.   #include <dpmi.h>
  315.  
  316.   #define _cdecl
  317.   #define _far
  318.   #define CLD
  319. #else
  320.   #define CLD _asm cld
  321. #endif
  322. #endif
  323. #endif
  324. #endif
  325. #endif
  326.  
  327. #ifdef __WATCOMC__
  328.   int matherr(struct exception *);     /* Math error traps. */
  329. #else
  330. #ifdef GCCDOS
  331.   int matherr(struct libm_exception *);
  332. #else
  333.   int _cdecl matherr(struct exception *);
  334. #endif
  335. #endif
  336.  
  337. #ifdef DITHERED
  338. signed short r_err[2][2050];          /* Allow up to 2048x??? resolutions. */
  339. signed short g_err[2][2050];
  340. signed short b_err[2][2050];
  341. #endif
  342.  
  343. /* The supported VGA adapter types 1 - 9, A - Z.  0 is for auto-detect. */
  344.  
  345. #define BASIC_VGA    1        /* 1 - Tested: AAC */
  346. #define MODE13x     2        /* 2 - Tested: AAC */
  347. #define TSENG3        3        /* 3 - Tested: William Minus */
  348. #define TSENG4        4        /* 4 - Tested: William Minus */
  349. #define VDC600        5        /* 5 - Tested: John Gooding */
  350. #define OAKTECH     6        /* 6 - Untested */
  351. #define VIDEO7        7        /* 7 - Untested */
  352. #define CIRRUS        8        /* 8 - Tested: AAC */
  353. #define PARADISE    9        /* 9 - Tested: John Degner */
  354. #define AHEADA        17        /* A - Untested */
  355. #define AHEADB        18        /* B - Untested */
  356. #define CHIPSTECH    19        /* C - Untested */
  357. #define ATIVGA        20        /* D - Tested: William Earl */
  358. #define EVEREX        21        /* E - Tested: A+B problem - Larry Minton */
  359. #define TRIDENT     22        /* F - Tested: A problem - Alexander Enzmann */
  360. #define VESA        23        /* G - Tested: Charles Marslett/AAC/BP */
  361. #define ATIXL        24        /* H - Tested: Randy Antler */
  362. #define PARADISE24X    25        /* I - Tested: Lutz Kretzschmar */
  363. /* J - N -- 5 more reserved SVGA adapter types */
  364. #define TRUECOLOR    31        /* >= O isn't an (S)VGA - note this is a "marker" display type only!!! */
  365. #define TIGA_16     31        /* O - Tested: Jay S. Curtis */
  366. #define TIGA_24     32        /* P - Tested: Jay S. Curtis */
  367. #define TRUE_640    33        /* Q - 640 x 480 truecolor Tested: Jay S. Curtis */
  368. #define TRUE_800    34        /* R - 800 x 600 truecolor Tested: Jay S. Curtis */
  369. #define TRUE_1024    35        /* S - 1024 x 768 truecolor Tested: Jay S. Curtis */
  370. #define TARGA        36        /* T - TARGA+ in AOM Tested: Aaron A. Collins */
  371. /* U - Z -- 6 more reserved Non-SVGA (True-Color) adapter types */
  372.  
  373.  
  374. #define MISCOUT     0x3c2        /* VGA chip msic output reg. addr */
  375. #define SEQUENCER    0x3c4        /* VGA chip sequencer register addr */
  376. #define CRTC        0x3d4        /* VGA chip crt controller reg addr */
  377.  
  378.  
  379. char *vga_names[] =
  380.     {                    /* POV-Ray command line option: */
  381.     "",                                 /* '0' is autodetect */
  382.     "Standard VGA",                     /*  1  */
  383.     "Simulated SVGA",                   /*  2  */
  384.     "Tseng Labs 3000 SVGA",             /*  3  */
  385.     "Tseng Labs 4000 SVGA",             /*  4  */
  386.     "AT&T VDC600 SVGA",                 /*  5  */
  387.     "Oak Technologies SVGA",            /*  6  */
  388.     "Video 7 SVGA",                     /*  7  */
  389.     "Video 7 Vega (Cirrus) VGA",        /*  8  */
  390.     "Paradise SVGA",                    /*  9  */
  391.     "",                                 /* misc ASCII */
  392.     "",
  393.     "",
  394.     "", /* reserved */
  395.     "",
  396.     "",
  397.     "",
  398.     "Ahead Systems Ver. A SVGA",        /*  A  */
  399.     "Ahead Systems Ver. B SVGA",        /*  B  */
  400.     "Chips & Technologies SVGA",        /*  C  */
  401.     "ATI SVGA",                         /*  D  */
  402.     "Everex SVGA",                      /*  E  */
  403.     "Trident SVGA",                     /*  F  */
  404.     "VESA Standard SVGA",               /*  G  */
  405.     "ATI VGA Wonder XL 32K Color SVGA", /*  H  */
  406.     "Diamond SpeedStar 24X SVGA",       /*  I  */
  407.     "",
  408.     "", /* spare SVGAs */
  409.     "",
  410.     "",
  411.     "",
  412.     "Hercules GWS/TIGA 16-bit",          /*  O   Here on is reserved for non-SVGA cards */
  413.     "Hercules GWS/TIGA 24-bit",          /*  P   TIGA is unsupported by the 32 bit compilers */
  414.     "TrueColor 640 x 480",               /*  Q  */
  415.     "TrueColor 800 x 600",               /*  R  */
  416.     "TrueColor 1024 x 768",              /*  S  */
  417.     "Truevision TARGA Plus"              /*  T  */
  418.     };
  419.  
  420.  
  421. unsigned int vptbl[] =        /* CRTC register values for MODE13x */
  422.     {
  423.     0x6b00,    /* horz total */
  424.     0x5901,    /* horz displayed */
  425.     0x5a02,    /* start horz blanking */
  426.     0x8e03U,    /* end horz blanking */
  427.     0x5e04,    /* start h sync */
  428.     0x8a05U,    /* end h sync */
  429.     0x0d06,    /* vertical total */
  430.     0x3e07,    /* overflow */
  431.     0x4009,    /* cell height */
  432.     0xea10U,    /* v sync start */
  433.     0xac11U,    /* v sync end and protect cr0-cr7 */
  434.     0xdf12U,    /* vertical displayed */
  435.     0x2d13,    /* offset */
  436.     0x0014,    /* turn off dword mode */
  437.     0xe715U,    /* v blank start */
  438.     0x0616,    /* v blank end */
  439.     0xe317U    /* turn on byte mode */
  440. };
  441.  
  442. unsigned short screen_height, screen_width;
  443. unsigned short svga_width = 640;       /* width of a scan line on the screen */
  444. unsigned short svga_height = 480;       /* number of scan lines on the screen */
  445. unsigned short svga_yincr = 640;       /* width of a scan line in video memory */
  446. int lastx, lasty, lastline;           /* Pixel / Line Caches */
  447. unsigned int x_off = 0;            /* Offsets for image centering option */
  448. unsigned int y_off = 0;
  449. int whichvga = BASIC_VGA;           /* BASIC_VGA mode by default */
  450. int vga_512K = FALSE;               /* Flag for whether or not >= 512K VGA mem */
  451. int bpp = 8;                   /* Number of bits per pixel */
  452. unsigned char cur_page = 255;           /* SVGA current page (bank) number */
  453. unsigned int map_code = 0;           /* Default map code is 0 */
  454. unsigned long gran = 65536L;           /* SVGA granule size (64K by default) */
  455. #ifdef _INTELC32_
  456. unsigned char *answer;               /* Code Builder answer area for VESA BIOS calls */
  457. #else
  458. #ifdef DOS16RM
  459. unsigned char *answer;               /* ZTC 16 answer area for VESA BIOS calls */
  460. static char save[260];
  461. unsigned long tl;
  462. #else
  463. #ifdef GCCDOS
  464. u_long buff;
  465. unsigned char answer[260];          /* GCC answer area for VESA BIOS calls */
  466. _go32_dpmi_seginfo dosinfo;
  467. int di_val, c_val, t_val, ds_val;
  468. #else
  469. #ifdef __WATCOMC__
  470. #ifdef __386__
  471. /* CCP - Added variables to save answer segment and selector */
  472. /*     - Changed name of vesabuffer to answerSel         */
  473. unsigned int answerSel;      /* Save area for the selector pointer */
  474. unsigned char *answer;         /* Watcom 386 answer area for VESA BIOS calls */
  475. #else
  476. unsigned char answer[260];     /* Answer area for VESA BIOS calls */
  477. #endif
  478. #else
  479. unsigned char answer[260];     /* Answer area for VESA BIOS calls */
  480. #endif
  481. #endif
  482. #endif
  483. #endif
  484. unsigned short vesamode;     /* Current VESA BIOS supported mode */
  485.  
  486. #if !defined(DOS386) && !defined(_INTELC32_) && !defined(__386__) && !defined(GCCDOS)
  487. int dither_matrix[4][4]=
  488.     {
  489.      {0,8,2,10},               /* HGWS/TIGA dither matrix */
  490.      {12,4,14,6},               /* this may not be needed? */
  491.      {3,11,1,9},
  492.      {15,7,13,5}
  493.     };
  494. char hpt[3];                   /* HWGS/TIGA information passing area */
  495. char _far *hptr=hpt;               /* HWGS/TIGA information passing area ptr */
  496. CONFIG config;
  497. #endif
  498.  
  499. DBL Height_Adjust = 1.0;           /* Fudge factors for SVGA scaling */
  500. DBL Width_Adjust = 1.0;
  501.  
  502. unsigned short pixel_len;
  503. unsigned short red_ndx, blue_ndx, green_ndx;
  504.  
  505. /* VESA VBE standard mode numbers */
  506.  
  507. struct {
  508.    unsigned short modenum;
  509.    unsigned short width;
  510.    unsigned short height;
  511.    unsigned short bpp;
  512.    unsigned short gsize;
  513.    } modelist[] = {{0x100, 640, 400, 8, 0}, {0x101, 640, 480, 8, 0},
  514.            {0x103, 800, 600, 8, 0}, {0x105, 1024, 768, 8, 0},
  515.            {0x107, 1280, 1024, 8, 0}, {0x10D, 320, 200, 16, 5},
  516.            {0x10E, 320, 200, 16, 6}, {0x10F, 320, 200, 24, 8},
  517.            {0x110, 640, 480, 16, 5}, {0x111, 640, 480, 16, 6},
  518.            {0x112, 640, 480, 24, 8}, {0x113, 800, 600, 16, 5},
  519.            {0x114, 800, 600, 16, 6}, {0x115, 800, 600, 24, 8},
  520.            {0x116, 1024, 768, 16, 5}, {0x117, 1024, 768, 16, 6},
  521.            {0x118, 1024, 768, 24, 8}, {0x119, 1280, 1024, 16, 5},
  522.            {0x11A, 1280, 1024, 16, 6}, {0x11B, 1280, 1024, 24, 8}};
  523.  
  524. unsigned int bitmask[] = {0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F,
  525.       0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF,
  526.       0x7FFF, 0xFFFF};
  527.  
  528. int r_shift, g_shift, b_shift;
  529. unsigned int r_mask, g_mask, b_mask;
  530.  
  531.  
  532. extern unsigned int Options;
  533. extern char DisplayFormat, PaletteOption, Color_Bits;
  534. extern int First_Line, Last_Line;
  535. extern int First_Column, Last_Column;
  536.  
  537.  
  538. int AutodetectVGA(void);
  539. int cirrus(void);
  540. int chkbank(unsigned int, unsigned int);
  541. void palette_init(void);
  542. void newbank(void);
  543. void set_palette_register(unsigned, unsigned, unsigned, unsigned);
  544. void hsv_to_rgb(DBL, DBL, DBL, unsigned *, unsigned *, unsigned *);
  545. void rgb_to_hsv(unsigned, unsigned, unsigned, DBL *, DBL *, DBL *);
  546. void atiplot(int, int, int, int, int);
  547. void box(int, int, int, int);
  548. int _cdecl box_fprintf( FILE *stream, char *format,...);
  549.  
  550. #ifdef DOS386
  551. void get_real_buf(short *real_buf, unsigned char _far **ptr);
  552.  
  553. static short real_buf[2];
  554. static unsigned char _far *real_ptr;
  555. #endif
  556.  
  557. /*
  558.     Note: for non-32-bit compilers, we can have a long in the struct and
  559.     still get word-aligned packing.  For 32-bit compilers, we want to use
  560.     all shorts so we don't force longword alignment of the members, which
  561.     can create gaps in the structure due to the member ordering within.
  562. */
  563.  
  564. typedef struct    /* TARGA+ I/O Command Array */
  565. {
  566.     unsigned short    IOCmd;        /*    Command Type        */
  567.     short        IOxi;        /*    Initial x position  */
  568.     short        IOxf;        /*    Final x position    */
  569.     short        IOyi;        /*    Initial y position  */
  570.     short        IOyf;        /*    Final y position    */
  571.     short        IOxd;        /*    Destination X        */
  572.     short        IOyd;        /*    Destination Y        */
  573. #if !defined(DOS16RM) && !defined(DOS386) && !defined(_INTELC32_) && !defined (__386__) && !defined(GCCDOS)
  574.     unsigned long    IOcolor;    /*    Color value        */
  575. #else
  576.     unsigned short    IOcolorLo;  /*    Color value Low Order */
  577.     unsigned short    IOcolorHi;  /*    Color value High Order */
  578. #endif
  579.     unsigned short    IORegsOff;  /*    Structure Buffer Ptr Offset*/
  580.     unsigned short    IORegsSeg;  /*    Structure Buffer Ptr Segment*/
  581.     unsigned short    IORLstOff;  /*    Register List Offset */
  582.     unsigned short    IORLstSeg;  /*    Register List Segment*/
  583.     unsigned short    IOBoardNum; /*    Active Board Number  */
  584.     unsigned short    IOStrucSiz; /*    Structure Size        */
  585. } TGACommand;
  586.  
  587. typedef TGACommand _far *TGACommandPtr;
  588. int TGAHandle;                /* global TARGA+ file handle used by open() */
  589.  
  590. #ifdef GCCDOS
  591. volatile unsigned short *TGARegs;    /* global TARGA+ register array Pointer */
  592. volatile TGACommandPtr command;     /* TARGA+ Command Structure Pointer */
  593. #else
  594. unsigned short tregs[130];
  595. TGACommand tcmd;            /* TARGA+ Command Structure */
  596. unsigned short *TGARegs = tregs;    /* global TARGA+ register array Pointer */
  597. TGACommandPtr command = &tcmd;        /* TARGA+ Command Structure Pointer */
  598. #endif
  599.  
  600. void SetTGARegs(int, int, union REGS*, struct SREGS*);
  601.  
  602. void display_init(width, height) /* Set video to requested or best mode */
  603.     int width, height;
  604.     {
  605.     char truc[80]; /* Truc bidon... */
  606.     union REGS inr, outr;
  607. #ifdef GCCDOS
  608.     _go32_dpmi_registers rdp;
  609.     char rep[256];
  610. #endif
  611.     struct SREGS segs;
  612.     unsigned char _far *fp;
  613. #ifdef DOS386
  614.     unsigned int tmp_word;
  615. #else
  616.     unsigned short _far *mp;
  617. #endif
  618.     unsigned int u, granule, vesamodes[64];
  619.     int i, maxvesamode;
  620.     time_t l, lt;
  621.     int show_display_type = FALSE;
  622.  
  623.     if (DisplayFormat == '?') {
  624.     DisplayFormat = '0';
  625.     show_display_type = TRUE;
  626.     }
  627. #ifdef __WATCOMC__
  628. #ifdef __386__
  629. /* CCP - Changed answer alloc to DPMI call to return segment and selector */
  630.     inr.x.ax = 0x0100;        /* DPMI allocate DOS memory */
  631.     inr.x.bx = 17;        /* Number of paragraphs requested */
  632.     int86(0x31, &inr, &inr);
  633.  
  634.       answerSel = inr.x.dx;    /* Save selector for free memory function */
  635.     answer =  (void *) ((inr.x.ax & 0xFFFF) << 4);
  636. /* CCP - End */
  637. #endif
  638. #endif
  639. #ifdef DOS16RM
  640.     display_base = (unsigned char *)D16SegAbsolute(0xA0000, 0);
  641.     answer = (unsigned char *)D16SegAbsolute(0x00580, 0x110);
  642.     for (u=0; u < 257; u++)
  643.     save[u] = answer[u];
  644. #endif
  645. #ifdef GCCDOS
  646. /*    if (DisplayFormat == '0' || DisplayFormat == VESA + '0' || DisplayFormat >= TRUECOLOR + '0')
  647. *    {
  648. *      dosinfo.size=17;
  649. *      if (_go32_dpmi_allocate_dos_memory(&dosinfo))
  650. *      {
  651. *         printf("Impossible d'allouer la mémoire conventionelle nécessaire...\n");
  652. *         exit(1);
  653. *     }
  654. *    }
  655. /*    else answer = NULL; */
  656.  
  657.     /* from the real mode offset (di_val) and the virtual addr of "answer", determine real DS segment value
  658.     ds_val = (unsigned int)((((unsigned long)answer & 0x0FFFFFFF) - (unsigned long)di_val) >> 4);
  659.  
  660.     command = (TGACommandPtr)(answer + 0x800);
  661.     TGARegs = (unsigned short *)(answer + 0x880);
  662.     c_val = di_val + 0x800;
  663.     t_val = di_val + 0x880;
  664.     */
  665. #endif
  666. #ifdef _INTELC32_
  667.     prev_int10 = _dos_getvect ( 0x10 );     /* Save previous handler pointer */
  668.     _dos_setvect ( 0x80000010, int10 );     /* Install user Int 10h handler */
  669.     if (_dos_allocmem(17, &answer) != 0) {  /* defined at the end of this file. */
  670.     printf ("Memory allocation failure for VESA detect.\n");
  671.     exit(1);
  672.     }
  673. #endif
  674. #ifdef DOS386
  675.    get_real_buf(real_buf, &real_ptr);
  676. #endif
  677.  
  678.     lastline = -1;         /* make sure we display the 1st line... */
  679.     screen_height = height;     /* requested screen height and width */
  680.     screen_width = width;
  681.  
  682. #ifdef DITHERED
  683. if (screen_width <= 2048) {
  684.     for (i=0; (unsigned short)i < screen_width + 2; i++) {
  685.     r_err[0][i] = 0;
  686.     r_err[1][i] = 0;
  687.     g_err[0][i] = 0;
  688.     g_err[1][i] = 0;
  689.     b_err[0][i] = 0;
  690.     b_err[1][i] = 0;
  691.     }
  692. }
  693. #endif
  694.  
  695.     if (DisplayFormat != '0')                   /* if not 0, some display type specified */
  696.     whichvga = (int)(DisplayFormat - '0');  /* de-ASCII-fy selection */
  697.     else {
  698.     whichvga = AutodetectVGA();
  699.     lt = l = time(&l);
  700.     if (show_display_type) {   /* If display format is ? */
  701.         printf("Display detected: (%c) %s Adapter", whichvga + '0', vga_names[whichvga]);
  702.         if (whichvga < TRUECOLOR)    /*  if not a True-Color graphics card */
  703.         printf(", with %s 512K RAM\n", vga_512K ? ">=" : "<");
  704.         else
  705.         printf("\nPausing...\n");
  706.         while (time(&l) < lt + 5);     /* display detected VGA type for 5 secs */
  707.               }
  708.     if (whichvga < TRUECOLOR && !vga_512K)    /* not enough RAM for 640 x 480? */
  709.         whichvga = MODE13x;     /* then try for next best mode... */
  710.     }
  711.  
  712.     if (whichvga < TRUECOLOR) { /* If an (S)VGA (not True-Color graphics card) */
  713.     if (whichvga == CIRRUS) /* Register Compatible VGA? */
  714.         whichvga = MODE13x; /* MODE13x if > 320x200, else... */
  715.  
  716.     if (screen_height <= 200 && screen_width <= 320 &&
  717.         PaletteOption != HICOLOR && PaletteOption != FULLCOLOR)
  718.         whichvga = BASIC_VGA;
  719.  
  720.     if (whichvga == TSENG4 && PaletteOption == HICOLOR) {
  721.         inr.x.ax = 0x10F1;        /* check and see if it's true... */
  722. #ifdef DOS386
  723.         int86_real(0x10, &inr, &inr);
  724. #else
  725.         int86(0x10, &inr, &inr);
  726. #endif
  727.         if ((int) inr.h.al != 0x10 || (int)inr.h.bl == 0) {
  728.         printf("Error - High Color Palette Option Unavailable\n");
  729. #ifdef _INTELC32_
  730.         _dos_setvect(0x10, prev_int10);   /* Restore previous handler */
  731.         _dos_freemem((unsigned) answer);  /* Free DOS buffer */
  732. #endif
  733.         exit(1);
  734.         }
  735.     }
  736.     }
  737.  
  738.     switch (whichvga) {
  739.     case MODE13x:
  740.         inr.x.ax = 0x0013;     /* Setup to VGA 360x480x256 (mode 13X) */
  741.         svga_width = 360;     /* Fake 640 mode actually is 360 */
  742.         svga_yincr = 90;
  743.         break;
  744.     case VDC600:
  745.         inr.x.ax = 0x005E;     /* Setup to VGA 640x400x256 (mode 5EH) */
  746.         svga_height = 400;     /* This is the only SVGA card w/400 Lines */
  747.         break;
  748.     case OAKTECH:
  749.         inr.x.ax = 0x0053;     /* Setup to VGA 640x480x256 most SVGAs */
  750.         break;
  751.     case AHEADA:
  752.     case AHEADB:
  753.         inr.x.ax = 0x0061;
  754.         break;
  755.     case EVEREX:
  756.         inr.x.ax = 0x0070;     /* BIOS Mode 0x16 for EV-678? */
  757.         inr.h.bl = 0x30;
  758.         break;
  759.     case ATIVGA:
  760.         if (screen_width <= 1024 && screen_height <= 768) {
  761.         inr.x.ax = 0x0064;
  762.         svga_width = 1024;
  763.         svga_height = 768;
  764.         svga_yincr = 1024;
  765.         }
  766.         if (screen_width <= 800 && screen_height <= 600) {
  767.         inr.x.ax = 0x0063;
  768.         svga_width = 800;
  769.         svga_height = 600;
  770.         svga_yincr = 800;
  771.         }
  772.         if (screen_width <= 640 && screen_height <= 480) {
  773.         inr.x.ax = 0x0062;
  774.         svga_width = 640;
  775.         svga_height = 480;
  776.         svga_yincr = 640;
  777.         }
  778.         break;
  779.     case ATIXL:
  780.         inr.x.ax = 0x0072;
  781.         svga_width = 640;
  782.         svga_height = 480;
  783.         svga_yincr = 640;
  784.         break;
  785.     case TRIDENT:
  786.         inr.x.ax = 0x005d;
  787.         break;
  788.     case VIDEO7:
  789.         inr.x.ax = 0x6f05;
  790.         inr.h.bl = 0x67;
  791.         break;
  792.     case CHIPSTECH:
  793.         if (screen_height <= 400) {
  794.         inr.x.ax = 0x0078;
  795.         svga_height = 400;
  796.         }
  797.         else
  798.         inr.x.ax = 0x0079;
  799.         break;
  800.     case PARADISE:
  801.         if (PaletteOption == HICOLOR)
  802.          {
  803.          if (screen_height <= 480 && screen_width <= 640) {
  804.               inr.x.ax = 0x0062;
  805.               svga_width = 640;
  806.               svga_height = 480;
  807.               svga_yincr = 640;
  808.          }
  809.          else {             /* 800 by 600 and beyond */
  810.               inr.x.ax = 0x0063;
  811.               svga_width = 800;
  812.               svga_height = 600;
  813.               svga_yincr = 800;
  814.          }
  815.          r_mask = g_mask = b_mask = 0xF8;
  816.          r_shift = 7;
  817.          g_shift = 2;            /* These are a left-shifts */
  818.          b_shift = 3;            /* This is a right-shift */
  819.          svga_yincr <<= 1;        /* two bytes per pixel */
  820.         }
  821.         else if (PaletteOption == FULLCOLOR)
  822.            /* Truecolor mode. Force 640x480 */
  823.         {
  824.           inr.x.ax = 0x006e;
  825.           svga_width = 640;
  826.           svga_height = 480;
  827.           svga_yincr = 640*3;        /* 3 bytes per pixel */
  828.           bpp = 24;
  829.           pixel_len = bpp/8;
  830.           red_ndx = 2;            /* Order in Frame buffer is RGB */
  831.           green_ndx = 1;
  832.           blue_ndx = 0;
  833.         } else /* Standard : 640x480 */
  834.           inr.x.ax = 0x005f;
  835.         if (PaletteOption == FULLCOLOR || PaletteOption == HICOLOR)
  836.         {
  837.          vga_512K = TRUE;         /* Always has 1MB */
  838.          whichvga=PARADISE24X;
  839.         }
  840.         break;
  841.     case PARADISE24X:
  842.         if (PaletteOption == HICOLOR)
  843.          {
  844.          if (screen_height <= 480 && screen_width <= 640) {
  845.               inr.x.ax = 0x0062;
  846.               svga_width = 640;
  847.               svga_height = 480;
  848.               svga_yincr = 640;
  849.          }
  850.          else {             /* 800 by 600 and beyond */
  851.               inr.x.ax = 0x0063;
  852.               svga_width = 800;
  853.               svga_height = 600;
  854.               svga_yincr = 800;
  855.          }
  856.          r_mask = g_mask = b_mask = 0xF8;
  857.          r_shift = 7;
  858.          g_shift = 2;            /* These are a left-shifts */
  859.          b_shift = 3;            /* This is a right-shift */
  860.          svga_yincr <<= 1;        /* two bytes per pixel */
  861.         }
  862.         else                /* Truecolor mode. Force 640x480 */
  863.         {
  864.           inr.x.ax = 0x0072;
  865.           svga_width = 640;
  866.           svga_height = 480;
  867.           svga_yincr = 640*3;        /* 3 bytes per pixel */
  868.           bpp = 24;
  869.           pixel_len = bpp/8;
  870.           red_ndx = 0;            /* Order in Frame buffer is RGB */
  871.           green_ndx = 1;
  872.           blue_ndx = 2;
  873.         }
  874.         vga_512K = TRUE;            /* Always has 1MB */
  875.         break;
  876.     case TSENG3:
  877.     case TSENG4:
  878.         if (screen_height <= 200 && screen_width <= 320) {
  879.          inr.x.ax = 0x0013;        /* setup to VGA 320x200 for 32K mode  */
  880.          svga_width = 320;        /* allow scaling to run at 320x200 */
  881.          svga_height = 200;
  882.          svga_yincr = 320;
  883.         }
  884.         else if (screen_height <= 350 && screen_width <= 640) {
  885.          inr.x.ax = 0x002D;
  886.          svga_height = 350;
  887.         }
  888.         else if (screen_height <= 400 && screen_width <= 640 && whichvga == TSENG4) {
  889.          inr.x.ax = 0x0078;
  890.          svga_height = 400;
  891.         }
  892.         else if (screen_height <= 480 && screen_width <= 640) {
  893.          inr.x.ax = 0x002E;
  894.         }
  895.         else {                /* 800 by 600 and beyond */
  896.          inr.x.ax = 0x0030;
  897.          svga_width = 800;
  898.          svga_height = 600;
  899.          svga_yincr = 800;
  900.         }
  901.         if ((screen_height > 600 || screen_width > 800) && whichvga == TSENG4) {
  902.         if (PaletteOption == HICOLOR) {
  903.             inr.x.ax = 0x0030;        /* Limit to 800x600 in HiColor mode */
  904.             svga_width = 800;
  905.             svga_height = 600;
  906.             svga_yincr = 800;
  907.         }
  908.         else {
  909.             inr.x.ax = 0x0038;
  910.             svga_width = 1024;
  911.             svga_height = 768;
  912.             svga_yincr = 1024;
  913.         }
  914.         }
  915.         break;
  916.     case VESA:
  917.         inr.x.ax = 0x4F00;            /* Call function 0 to get VGA info */
  918. #ifdef _INTELC32_
  919.         for (u=0; u<256; u++)
  920.         answer[u] = 0;
  921.         inr.w.edi = (unsigned)answer;
  922.         int86(0x10, &inr, &outr);        /* Get thru int 10h inr outr */
  923. #else
  924. #ifdef DOS386
  925.         for (u=0; u<256; u++)
  926.         real_ptr[u] = 0;
  927.         inr.x.di = real_buf[0];        /* deposit results here */
  928.         segread(&segs);            /* get our DS, etc. */
  929.         segs.es = real_buf[1];        /* get segment of answer */
  930.         int86x_real(0x10, &inr, &outr, &segs);
  931.         for(u=0; u<sizeof(answer); u++)
  932.         answer[u] = real_ptr[u];
  933. #else
  934. #ifdef GCCDOS
  935.         buff=_go32_info_block.linear_address_of_transfer_buffer;
  936.         memset(&rdp,0,sizeof(rdp));
  937.         for (u=0; u<256; u++)
  938.         answer[u] = 0;
  939.         rdp.x.ax = 0x4f00;
  940.         rdp.x.di = (buff & 0xf);
  941.         rdp.x.es= buff >> 4;        /* deposit results here */
  942.         _go32_dpmi_simulate_int(0x10,&rdp);
  943.  
  944.         dosmemget(buff,256,answer);
  945. #else
  946. #ifdef DOS16RM
  947.         for (u=0; u<256; u++)
  948.         answer[u] = 0;
  949.         segread(&segs);            /* get our DS, etc. */
  950.         inr.x.di = 0x580;            /* deposit results here */
  951.         segs.es = 0;            /* get segment of answer */
  952.         int86x(0x10, &inr, &outr, &segs);
  953. #else
  954. /* CCP - Added Watcom section */
  955. #ifdef __WATCOMC__
  956. #ifdef __386__
  957.         for (u=0; u<256; u++)        /* clear answer buffer */
  958.         answer[u] = 0;
  959.  
  960.            /* Set up real-mode call structure */
  961.  
  962.         memset(&RMI, 0, sizeof(RMI));
  963.         RMI.EAX = 0x4F00;         /* Call function 0 to get VGA info */
  964.         RMI.ES = D32RealSeg(answer); /* put DOS seg:off of answer into es:di */
  965.           RMI.EDI = D32RealOff(answer);
  966.  
  967.         segread(&segs);         /* init our selectors */
  968.         inr.x.ax = 0x0300;
  969.         inr.x.bx = 0x10;
  970.         inr.x.cx = 0;
  971.         segs.es = FP_SEG(&RMI);     /* get segment of rmi */
  972.         inr.x.di = FP_OFF(&RMI);     /* deposit results here */
  973.         int86x(0x31, &inr, &outr, &segs);
  974.            outr.x.ax = RMI.EAX;   /* for code below */
  975. #endif
  976. /* CCP - End */
  977. #else
  978.         for (u=0; u<256; u++)        /* clear answer buffer */
  979.         answer[u] = 0;
  980.         inr.x.di = FP_OFF(answer);        /* deposit results here */
  981.         segread(&segs);            /* get our DS, etc. */
  982.         segs.es = FP_SEG(answer);        /* get segment of answer */
  983.         int86x(0x10, &inr, &outr, &segs);
  984. #endif
  985. #endif
  986. #endif
  987. #endif
  988. #endif
  989. #ifdef GCCDOS
  990.         if ( rdp.x.ax != 0x004f ||
  991. #else
  992.         if ( outr.x.ax != 0x004F ||
  993. #endif
  994.          answer[0] != 'V' ||
  995.             answer[1] != 'E' || answer[2] != 'S' ||
  996.             answer[3] != 'A' ) {          /* if response unsuccessful */
  997.         printf("Error - VESA BIOS Extensions Not Available: code=%04X<%c%c%c%c>\n",
  998. #ifdef GCCDOS
  999.             rdp.x.ax,
  1000. #else
  1001.             outr.x.ax,
  1002. #endif
  1003.             answer[0],answer[1],answer[2],answer[3]);
  1004. #ifdef DOS16RM
  1005.         for (u=0; u < 257; u++)
  1006.             answer[u] = save[u];
  1007. #endif
  1008. #ifdef _INTELC32_
  1009.         _dos_setvect(0x10, prev_int10);   /* Restore previous handler */
  1010.         _dos_freemem((unsigned) answer);  /* Free DOS buffer */
  1011. #endif
  1012.         exit(1);
  1013.         }
  1014. #ifdef _INTELC32_
  1015.         mp = (char *)(*(unsigned short *)(answer + 14) +
  1016.              (((long)*(unsigned short *)(answer + 16)) << 4));
  1017.         for (i = 0; i < 64 && mp[i] != 0xFFFF; i++)    /* for all modes available */
  1018.         vesamodes[i] = mp[i];               /* copy to local mode list */
  1019. #else
  1020. #ifdef DOS386
  1021.         fp = MK_FP(_x386_zero_base_selector,
  1022.         *(unsigned short *)(answer+14)    /* get mode tbl. pointer   */
  1023.         + (*(unsigned short *)(answer+16) << 4));
  1024.         for (u=i=0; i < 64 && (tmp_word=fp[u]|(fp[u+1]<<8)) != 0xFFFF; i++, u += 2)/* for all modes available */
  1025.         vesamodes[i] = tmp_word;    /* copy to local mode list */
  1026. #else
  1027. #ifdef DOS16RM
  1028.         tl = *(unsigned short *)(answer + 14) +
  1029.           (((long)*(unsigned short *)(answer + 16)) << 4);
  1030.         mp = (unsigned short *)D16SegAbsolute(tl, 0);
  1031.         for (i = 0; i < 64 && mp[i] != 0xFFFF; i++) /* for all modes available */
  1032.         vesamodes[i] = mp[i];            /* copy to local mode list */
  1033.         D16SegCancel((void *)mp);
  1034. #else
  1035.         mp = (unsigned short *)MK_FP(answer[16]+(answer[17]<<8),
  1036.                answer[14]+(answer[15]<<8));      /* get mode tbl. pointer */
  1037.         for (i = 0; i < 64 && mp[i] != 0xFFFF; i++)   /* for all modes available */
  1038.         vesamodes[i] = mp[i];              /* copy to local mode list */
  1039. #endif
  1040. #endif
  1041. #endif
  1042.  
  1043. /* Get VESA modes attributes list. */
  1044.         maxvesamode = i;            /* note end of list */
  1045.         bpp = (PaletteOption == HICOLOR)? 16: (PaletteOption == FULLCOLOR)? 32: 8;
  1046.  
  1047.         svga_width = 0;
  1048.         svga_height = 0;
  1049.         vesamode = 0;
  1050.         for (i = 0; i < maxvesamode; i++) {
  1051. #ifdef GCCDOS
  1052.   rdp.x.ax=0x4f01;
  1053.   rdp.x.bx=rdp.x.cx=vesamodes[i];
  1054. #else
  1055.         inr.x.ax = 0x4F01;            /* VESA BIOS fetch attributes call */
  1056.         inr.x.bx = inr.x.cx = vesamodes[i]; /* Get attrs for mode */
  1057. #endif
  1058. #ifdef _INTELC32_
  1059.         inr.w.edi = (unsigned)answer;        /* Stash results here. */
  1060.         int86(0x10, &inr, &outr);
  1061. #else
  1062. #ifdef DOS386
  1063.         inr.x.di = real_buf[0];         /* Deposit results here */
  1064.         segread(&segs);             /* Get our DS, etc. */
  1065.         segs.es = real_buf[1];            /* Get segment of answer */
  1066.         int86x_real(0x10, &inr, &outr, &segs);
  1067.         for(u=0; u<sizeof(answer); u++)
  1068.             answer[u] = real_ptr[u];
  1069. #else
  1070. #ifdef GCCDOS
  1071.         buff=_go32_info_block.linear_address_of_transfer_buffer;
  1072.         rdp.x.di=buff & 0xf;
  1073.         rdp.x.es=buff >> 4;
  1074.         _go32_dpmi_simulate_int(0x10,&rdp);
  1075.         dosmemget(buff,260,answer);
  1076. #else
  1077. #ifdef DOS16RM
  1078.         segread(&segs);             /* get our DS, etc. */
  1079.         inr.x.di = 0x580;            /* deposit results here */
  1080.         segs.es = 0;
  1081.         int86x(0x10, &inr, &outr, &segs);   /* BIOS fetch attrib call */
  1082. /* CCP - Added watcom section */
  1083. #else
  1084. #ifdef __WATCOMC__
  1085. #ifdef __386__
  1086.  
  1087.         memset(&RMI, 0, sizeof(RMI));
  1088.         RMI.EAX = 0x4F01;           /* VESA BIOS fetch attributes call */
  1089.         RMI.ECX = vesamodes[i];
  1090.         RMI.ES = D32RealSeg(answer);   /* put DOS seg:off of answer into es:di */
  1091.         RMI.EDI = D32RealOff(answer);
  1092.  
  1093.         segread(&segs);           /* init our selectors */
  1094.         inr.x.ax = 0x0300;
  1095.         inr.x.bx = 0x10;
  1096.         inr.x.cx = 0;
  1097.         segs.es = FP_SEG(&RMI);        /* get segment of rmi */
  1098.         inr.x.di = FP_OFF(&RMI);        /* deposit results here */
  1099.         int86x(0x31, &inr, &outr, &segs);
  1100.         inr.x.cx = RMI.ECX;         /* for debug code below */
  1101. #endif
  1102. #else
  1103.         inr.x.di = FP_OFF(answer);        /* deposit attribs here */
  1104.         segread(&segs);             /* get our DS, etc. */
  1105.         segs.es = FP_SEG(answer);        /* get segment of answer */
  1106.         int86x(0x10, &inr, &outr, &segs);   /* BIOS fetch attrib call */
  1107. #endif
  1108. #endif
  1109. #endif
  1110. #endif
  1111. #endif
  1112.         if ((answer[0] & 0x11) != 0x11)
  1113.             continue;
  1114.         if ((answer[0] & 0x02) == 0) {
  1115. #ifdef DEBUG_VIDEO
  1116.             printf("VESA mode without full information found [%03X]\n",
  1117.                 inr.x.cx);
  1118. #endif
  1119.             for (u=0; u < sizeof(modelist)/sizeof(modelist[0]); u++)
  1120.             if (vesamodes[i] == modelist[u].modenum) {
  1121.                 *(unsigned short *)(answer+18) = modelist[u].width;
  1122.                 *(unsigned short *)(answer+20) = modelist[u].height;
  1123.                 answer[25] = (unsigned char)modelist[u].bpp;
  1124.                 answer[36] = 0;
  1125.                 if (answer[25] == 16) {
  1126.                 answer[31] = 5;
  1127.                 answer[32] = (unsigned char)(modelist[u].gsize + 5);
  1128.                 answer[33] = (unsigned char)modelist[u].gsize;
  1129.                 answer[34] = 5;
  1130.                 answer[35] = 5;
  1131.                 }
  1132.                 else if (answer[25] == 24 || answer[25] == 32) {
  1133.                 answer[31] = (unsigned char)modelist[u].gsize;
  1134.                 answer[32] = (unsigned char)(modelist[u].gsize * 2);
  1135.                 answer[33] = (unsigned char)modelist[u].gsize;
  1136.                 answer[34] = (unsigned char)modelist[u].gsize;
  1137.                 answer[35] = (unsigned char)modelist[u].gsize;
  1138.                 }
  1139.                 answer[0] |= 0x02;
  1140.                 break;
  1141.             }
  1142.         }
  1143.         else if (answer[25] == 16 && answer[31] == 0 && answer[33] == 0 &&
  1144.             answer[35] == 0) {
  1145. #ifdef DEBUG_VIDEO
  1146.             printf("VESA 1.1 extended information found for mode %03X\n",
  1147.                 inr.x.cx);
  1148. #endif
  1149.             answer[31] = 5;    /* VESA 1.1 Programming guideline */
  1150.             answer[32] = 10;    /* default high color is 5-5-5 */
  1151.             answer[33] = 5;
  1152.             answer[34] = 5;
  1153.             answer[35] = 5;
  1154.         }
  1155.  
  1156.         if ((answer[0] & 0x02) && ((int)answer[25] == bpp ||
  1157.             (bpp == 32 && (int)answer[25] == 24) ||
  1158.             (bpp == 15 || bpp == 16 && (int)answer[25] == 15))) {
  1159.             if ((svga_height < screen_height || svga_width < screen_width) &&
  1160.                 *(unsigned short *)(answer+18) >= svga_width &&
  1161.                 *(unsigned short *)(answer+20) >= svga_height)
  1162.             vesamode = vesamodes[i];
  1163.             else if (svga_height >= *(unsigned short *)(answer+18) &&
  1164.                 svga_width >= *(unsigned short *)(answer+20) &&
  1165.                 *(unsigned short *)(answer+18) >= screen_width &&
  1166.                 *(unsigned short *)(answer+20) >= screen_height)
  1167.             vesamode = vesamodes[i];
  1168.  
  1169.             if (vesamode == vesamodes[i]) {
  1170. #ifdef DEBUG_VIDEO
  1171.             printf("VESA mode selected: %03X\n", vesamodes[i]);
  1172. #endif
  1173.             if ((answer[2] & 0x05) == 0x05)
  1174.                 map_code = 0x0000;             /* Select A page */
  1175.             else if ((answer[3] & 0x05) == 0x05)
  1176.                 map_code = 0x0001;             /* Select B page */
  1177.             bpp = answer[25];             /* Handle 24 or 32 bpp */
  1178.             svga_width = *(unsigned short *)(answer+18);
  1179.             svga_height = *(unsigned short *)(answer+20);
  1180.             r_shift = answer[32] + answer[31] - 8;
  1181.             g_shift = answer[34] + answer[33] - 8;
  1182.             b_shift = answer[36] + answer[35] - 8;
  1183.             r_mask = 0xFF - bitmask[8 - answer[31]];
  1184.             g_mask = 0xFF - bitmask[8 - answer[33]];
  1185.             b_mask = 0xFF - bitmask[8 - answer[35]];
  1186.             b_shift = - b_shift;
  1187.             if (bpp == 16 && (b_shift < 0 || r_shift < 0 || g_shift < 0)) {
  1188.                 printf("Adapter not supported currently in high color modes!\n");
  1189.                 printf("Shifts required are RED:%d, GREEN:%d, BLUE:%d\n",
  1190.                     r_shift, g_shift, b_shift);
  1191.                 printf("Bit masks: RED:%d, GREEN:%d, BLUE:%d\n",
  1192.                     r_mask, g_mask, b_mask);
  1193.                 printf("Field positions: RED:%d, GREEN:%d, BLUE:%d\n",
  1194.                     answer[36], answer[34], answer[32]);
  1195.                 printf("Field widths: RED:%d, GREEN:%d, BLUE:%d\n",
  1196.                     answer[35], answer[33], answer[31]);
  1197.                 exit(1);
  1198.             }
  1199.             }
  1200.         }
  1201.         }
  1202.  
  1203.         if (vesamode == 0){
  1204.         lt = time(&l);
  1205.         printf("\nSelected VESA Mode could not be initialized!!!\n");
  1206.         printf("If you are trying to use HiColor or TrueColor modes they\n");
  1207.         printf("may not be supported by your VESA BIOS.\n\n");
  1208.         printf("Using standard 320x200x256 VGA for this run.\n");
  1209.         printf("\nPausing 10 seconds...\n");
  1210.         while (time(&l) < lt + 10);
  1211.         goto no_valid_mode;
  1212.         }
  1213.  
  1214. #ifdef GCCDOS
  1215.   rdp.x.ax= 0x4f01;
  1216.   rdp.x.bx=rdp.x.cx=vesamode;
  1217. #else
  1218.         inr.x.ax = 0x4F01;            /* VESA BIOS fetch attributes call */
  1219.         inr.x.bx = inr.x.cx = vesamode;    /* Get attrs for mode */
  1220. #endif
  1221. #ifdef _INTELC32_
  1222.         inr.w.edi = (unsigned)answer;    /* Stash results here. */
  1223.         int86(0x10, &inr, &outr);        /* Get thru INT 10     */
  1224. #else
  1225. #ifdef GCCDOS
  1226.         buff=_go32_info_block.linear_address_of_transfer_buffer;
  1227.         rdp.x.di=buff & 0xf;
  1228.         rdp.x.es=buff >> 4;
  1229.         _go32_dpmi_simulate_int(0x10,&rdp);
  1230.         dosmemget(buff,260,answer);
  1231. #else
  1232. #ifdef DOS386
  1233.         inr.x.di = real_buf[0];        /* Deposit results here */
  1234.         segread(&segs);            /* Get our DS, etc. */
  1235.         segs.es = real_buf[1];        /* Get segment of answer */
  1236.         int86x_real(0x10, &inr, &outr, &segs);
  1237.         for(u=0; u<sizeof(answer); u++)
  1238.         answer[u] = real_ptr[u];
  1239. #else
  1240. #ifdef DOS16RM
  1241.         segread(&segs);            /* Get our DS, etc. */
  1242.         inr.x.di = 0x580;            /* Deposit results here */
  1243.         segs.es = 0;
  1244.         int86x(0x10, &inr, &outr, &segs);
  1245. /* CCP - Added watcom section */
  1246. #else
  1247. #ifdef __WATCOMC__
  1248. #ifdef __386__
  1249.         memset(&RMI, 0, sizeof(RMI));
  1250.         RMI.EAX = 0x4F01;            /* VESA BIOS fetch attributes call */
  1251.         RMI.ECX = vesamode;         /* Get attrs for mode */
  1252.         RMI.ES = D32RealSeg(answer);    /* put DOS seg:off of answer into es:di */
  1253.         RMI.EDI = D32RealOff(answer);
  1254.  
  1255.         segread(&segs);            /* init our selectors */
  1256.         inr.x.ax = 0x0300;
  1257.         inr.x.bx = 0x10;
  1258.         inr.x.cx = 0;
  1259.         segs.es = FP_SEG(&RMI);        /* get segment of rmi */
  1260.         inr.x.di = FP_OFF(&RMI);        /* deposit results here */
  1261.         int86x(0x31, &inr, &outr, &segs);
  1262.         outr.x.ax = RMI.EAX;        /* for code below */
  1263.  
  1264. #endif
  1265. /* CCP - End */
  1266. #else
  1267.         inr.x.di = FP_OFF(answer);        /* Deposit attribs here */
  1268.         segread(&segs);            /* Get our DS, etc. */
  1269.         segs.es = FP_SEG(answer);        /* Get segment of answer */
  1270.         int86x(0x10, &inr, &outr, &segs);    /* BIOS fetch attrib call */
  1271. #endif
  1272. #endif
  1273. #endif
  1274. #endif
  1275. #endif
  1276. #ifdef GCCDOS
  1277.         if (rdp.x.ax != 0x004F){
  1278. #else
  1279.         if (outr.x.ax != 0x004F){
  1280. #endif
  1281.            lt = time(&l);
  1282.         printf("\nSelected VESA Mode could not be initialized!!!\n");
  1283.         printf("If you are trying to use HiColor or TrueColor modes they\n");
  1284.         printf("may not be supported by your VESA BIOS.\n\n");
  1285.         printf("Using standard 320x200x256 VGA for this run.\n");
  1286.         printf("\nPausing 10 seconds...\n");
  1287.         while (time(&l) < lt + 10);
  1288.         goto no_valid_mode;
  1289.         }
  1290.         svga_yincr = *(unsigned short *)(answer+16);
  1291.         granule = *(unsigned short *)(answer + 4); /* "granule" size */
  1292.         if (granule < 1)
  1293.         granule = 1;
  1294.         gran = 1024L * granule;
  1295.  
  1296.         inr.x.ax = 0x4F02;         /* VESA BIOS initialize video mode call */
  1297. #ifdef __WATCOMC__
  1298. #ifdef __386__
  1299.         inr.x.ebx = vesamode;    /* CCP BP */
  1300. #endif
  1301. #endif
  1302. #ifdef GCCDOS
  1303.   inr.x.bx=inr.x.cx=vesamode;
  1304. #endif
  1305.         if (svga_yincr == svga_width && PaletteOption == HICOLOR)
  1306.         if (svga_width == 640 && svga_height == 200) {
  1307.             svga_width = 320;
  1308.             svga_yincr = 1024;
  1309.         }
  1310.         else {
  1311.             svga_yincr = svga_width * 2;
  1312.         }
  1313.         if (PaletteOption == FULLCOLOR) {
  1314.         if (r_shift == 0 && g_shift == 0 && b_shift == 0) {
  1315.             r_shift = 16;
  1316.             g_shift = 8;
  1317.             b_shift = 0;
  1318.         }
  1319.         if (r_mask != 0xFF || g_mask != 0xFF || b_mask != 0xFF ||
  1320.             (r_shift & 0x07) || (g_shift & 0x07) || (b_shift & 0x07)) {
  1321.             printf("Adapter not supported currently in full color modes!\n");
  1322.             printf("Shifts required are RED:%d, GREEN:%d, BLUE:%d\n",
  1323.                 r_shift, g_shift, b_shift);
  1324.             printf("Bit masks: RED:0x%02x, GREEN:0x%02x, BLUE:0x%02x\n",
  1325.                 r_mask, g_mask, b_mask);
  1326.             printf("Field positions: RED:%d, GREEN:%d, BLUE:%d\n",
  1327.                 answer[36], answer[34], answer[32]);
  1328.             printf("Field widths: RED:%d, GREEN:%d, BLUE:%d\n",
  1329.                 answer[35], answer[33], answer[31]);
  1330.             exit(1);
  1331.         }
  1332.         red_ndx = r_shift >> 3;
  1333.         green_ndx = g_shift >> 3;
  1334.         blue_ndx = (-b_shift) >> 3;
  1335.         pixel_len = bpp/8;
  1336. #ifdef DEBUG_VIDEO
  1337.         printf("Byte offsets: R=%d, G=%d, B=%d\n", red_ndx, green_ndx,
  1338.             blue_ndx);
  1339. #endif
  1340.         }
  1341.         break;
  1342.  
  1343. #if !defined(DOS386) && !defined(_INTELC32_) && !defined(__386__) && !defined(GCCDOS)
  1344.     case TIGA_16:            /* Set up TIGA modes. Real mode compilers only. */
  1345.     case TIGA_24:
  1346.     case TRUE_640:
  1347.     case TRUE_800:
  1348.     case TRUE_1024:
  1349.         if ((int)(DisplayFormat - '0') == whichvga)    /* not autodetected */
  1350.         if (tiga_set(CD_OPEN) < 0)           /* Attempt to open the TIGA CD */
  1351.             {
  1352.             printf("Error - TIGA CD Not Installed.");
  1353.             goto TIGA_error;
  1354.         }
  1355.         if (!set_videomode(TIGA, INIT_GLOBALS | CLR_SCREEN))
  1356.         {
  1357.         printf("Error #1 Initializing TIGA.");
  1358.         goto TIGA_error;
  1359.         }
  1360.         if (install_primitives() < 0)           /* load if not already loaded */
  1361.         {
  1362.         if (!set_videomode(TIGA, INIT))        /* reinit if due to full heap */
  1363.         {
  1364.             printf("Error #2 Initializing TIGA.");
  1365.             goto TIGA_error;
  1366.         }
  1367.         else if (install_primitives() < 0)
  1368.         {
  1369.             printf("Error Installing TIGA Primitives.");
  1370. TIGA_error:
  1371. #ifdef DOS16RM
  1372.             for (u=0; u < 257; u++)
  1373.             answer[u] = save[u];
  1374. #endif
  1375.             exit(1);
  1376.         }
  1377.         switch (whichvga)
  1378.             {
  1379.             case TIGA_16:    /* initialize demo globals */
  1380.              get_config(&config);
  1381.              if ((config.mode.disp_vres == 640) && (config.mode.disp_psize == 16))
  1382.              {
  1383.                 Color_Bits = 5;
  1384.                 svga_width = 640;
  1385.                 svga_height = 480;
  1386.                 svga_yincr = 640;
  1387.                 set_config(1,0);        /* 16 bit (was 2,0 ???? - AAC) */
  1388.                 break;
  1389.              }
  1390.              else whichvga = TIGA_24;
  1391.             case TIGA_24:
  1392.             get_config(&config);
  1393.             if ((config.mode.disp_vres == 480) && (config.mode.disp_hres == 512))
  1394.             {
  1395.                 svga_width = 512;       /* NTSC standard television resolution */
  1396.                 svga_height = 480;
  1397.                 svga_yincr = 512;
  1398.                 set_config(4,0);       /* 24 bit */
  1399.                 break;
  1400.             }
  1401.             else whichvga = TRUE_640;
  1402.             case TRUE_640:
  1403.             get_config(&config);
  1404.             if ((config.mode.disp_hres == 640) && (config.mode.disp_psize == 32))
  1405.             {
  1406.                 svga_width = 640;
  1407.                 svga_height = 480;
  1408.                 svga_yincr = 640;
  1409.                 set_config(0,0);       /* 24 bit */
  1410.                 break;
  1411.             }
  1412.             else whichvga = TRUE_800;
  1413.            case TRUE_800:
  1414.             get_config(&config);
  1415.             if ((config.mode.disp_vres == 600) && (config.mode.disp_hres == 800))
  1416.             {
  1417.                 svga_width = 800;
  1418.                 svga_height = 600;
  1419.                 svga_yincr = 800;
  1420.                 set_config(2,0);       /* 24 bit */
  1421.                 break;
  1422.             }
  1423.             else whichvga = TRUE_1024;
  1424.            case TRUE_1024:
  1425.             svga_width = 1024;
  1426.             svga_height = 768;
  1427.             svga_yincr = 1024;
  1428.             set_config(4,0);
  1429.            }
  1430.            }
  1431.         break;
  1432. #endif
  1433.     case TARGA:        /* TARGA Plus board in Advanced Operating Mode */
  1434.         TGAHandle = open("TARGPLUS", O_RDWR | O_BINARY );   /* equivalent to TARGA+ "GraphInit() call */
  1435.         if (TGAHandle != -1) {                /* equivalent to TARGA+ "SetRawMode()" call */
  1436.         inr.x.ax = 0x4400;                /* get current info on device */
  1437.         inr.x.bx = TGAHandle;                /* TARGA+ handle */
  1438. #ifdef DOS386
  1439.         int86_real(0x21, &inr, &inr);
  1440. #else
  1441.         int86(0x21, &inr, &inr);
  1442. #endif
  1443.         inr.h.dh = 0;
  1444.         inr.h.dl |= 0x20;             /* or in 'RAW' bit. */
  1445. #ifdef DEBUG_VIDEO
  1446.         printf("DIAG: inr.h.dl = %02X\n", inr.h.dl & 0x00FF);
  1447. #endif
  1448.         inr.x.ax = 0x4401;             /* write it back */
  1449. #ifdef DOS386
  1450.         int86_real(0x21, &inr, &inr);
  1451. #else
  1452.         int86(0x21, &inr, &inr);         /* status of operation is !regs.x.cflag */
  1453. #endif
  1454. #ifdef DEBUG_VIDEO
  1455.         diaged = FALSE;
  1456.         printf("DIAG: SetTGARegs(5, 0) -");
  1457. #endif
  1458.         SetTGARegs( 5, 0, &inr, &segs);       /* equivalent to TARGA+ "ResetBoard()" call */
  1459. #ifdef DOS386
  1460.         int86x_real(0x21, &inr, &inr, &segs);
  1461. #else
  1462.         int86x(0x21, &inr, &inr, &segs);       /* call DOS */
  1463. #endif
  1464. #ifdef DEBUG_VIDEO
  1465.         diaged = FALSE;
  1466.         printf("DIAG: SetTGARegs(0,1) -");
  1467. #endif
  1468.         SetTGARegs( 0, 1, &inr, &segs);        /* equivalent to TARGA+ "ReadAll()" call */
  1469. #ifdef GCCDOS
  1470.         command->IORegsOff = (unsigned short)t_val;    /* real mode offset pointer to TGARegs structure */
  1471.         command->IORegsSeg = (unsigned short)ds_val;
  1472. #else
  1473.         command->IORegsOff = (unsigned short)FP_OFF(TGARegs);    /* pointer to structure */
  1474.         command->IORegsSeg = (unsigned short)FP_SEG(TGARegs);
  1475. #endif
  1476. #ifdef DEBUG_VIDEO
  1477.         printf("DIAG: command = %p, TGARegs = %p, IORegsOff = %04X, IORegsSeg = %04X\n", command, TGARegs, command->IORegsOff, command->IORegsSeg);
  1478. #endif
  1479. #ifdef DOS386
  1480.         int86x_real(0x21, &inr, &inr, &segs);
  1481. #else
  1482.         int86x(0x21, &inr, &inr, &segs);           /* call DOS */
  1483. #endif
  1484.         svga_width = TGARegs[0];               /* sense frame buffer width and height */
  1485.         svga_height = TGARegs[1];
  1486.         if (show_display_type) {
  1487.             printf("Current Display Mode: %dx%d\n", svga_width, svga_height);
  1488.             while (time(&l) < lt + 5)               /* display detected Display Mode for 5 secs */
  1489.             ;
  1490.         }
  1491.         if (!svga_width || !svga_height) {
  1492.             printf("Error - TARGA Plus Registers Read Invalid Values\n");
  1493. #ifdef _INTELC32_
  1494.             _dos_setvect(0x10, prev_int10);   /* Restore previous handler */
  1495.             _dos_freemem((unsigned) answer);  /* Free DOS buffer */
  1496. #endif
  1497.             exit(1);
  1498.         }
  1499.         }
  1500.         else {
  1501.         printf("Error Opening TARGA+ Device - TARGAP.SYS driver not installed?\n");
  1502. #ifdef _INTELC32_
  1503.         _dos_setvect(0x10, prev_int10);/* Restore previous handler */
  1504.         _dos_freemem((unsigned) answer);/* Free DOS buffer */
  1505. #endif
  1506.         exit(1);
  1507.         }
  1508.         break;
  1509.  
  1510. default:        /* BASIC_VGA */
  1511. no_valid_mode:
  1512.         if ((PaletteOption == HICOLOR) || (PaletteOption == FULLCOLOR))
  1513.            PaletteOption=P_332;
  1514.         inr.x.ax = 0x0013;    /* setup to VGA 320x200x256 (mode 13H) */
  1515.         svga_width = 320;    /* allow scaling to run at 320x200 */
  1516.         svga_height = 200;
  1517.         svga_yincr = 320;
  1518.         bpp = 8;
  1519.         break;
  1520.     }
  1521.  
  1522.     if (whichvga >= TRUECOLOR)    /* if True-Color then it has no palette */
  1523.     goto exit_point;
  1524.  
  1525. #ifdef DEBUG_VIDEO
  1526.     lt = l = time(&l);
  1527.     printf("Display detected: (%c) %s Adapter", whichvga + '0', vga_names[whichvga]);
  1528.     if (whichvga < TRUECOLOR)                 /*  if not a True-Color graphics card */
  1529.     printf(", with %s 512K RAM", vga_512K ? ">=" : "<");
  1530.     printf("\n   ax=%04X, bx=%04X, cx=%04X\n", inr.x.ax, inr.x.bx, inr.x.cx);
  1531.     printf("   %dx%d, yincr=%d\n", svga_width, svga_height, svga_yincr);
  1532.     printf("   shifts(R,G,B)=%d,%d,%d\n", r_shift, g_shift, b_shift);
  1533.     printf("   masks(R,G,B) =%d,%d,%d\n", r_mask, g_mask, b_mask);
  1534.     while (time(&l) < lt + 5)                   /* display detected VGA type for 5 secs */
  1535.     ;
  1536. #endif
  1537.  
  1538. #ifdef DOS386
  1539.     int86_real(0x10, &inr, &outr);  /* do the BIOS video mode sel. call */
  1540. #else
  1541.     int86(0x10, &inr, &outr);        /* do the BIOS video mode sel. call */
  1542. #endif
  1543.  
  1544.     if (whichvga == MODE13x) {        /* Tweak VGA registers to get higher res! */
  1545.     outpw(SEQUENCER, 0x0604);   /* disable chain 4 */
  1546.     outpw(SEQUENCER, 0x0F02);   /* allow writes to all planes */
  1547. #ifdef DOS386
  1548.     fp = MK_FP(_x386_zero_base_selector, 0xA0000);
  1549. #else
  1550. #ifdef DOS16RM
  1551.     fp = display_base;
  1552. #else
  1553.     fp = MK_FP(0xA000, 0);
  1554. #endif
  1555. #endif
  1556.     for (u = 0; u < 43200; u++) {           /* clear the whole screen */
  1557.         fp = (unsigned char *)MK_FP(0xA000, u);
  1558.         *fp = 0;                   /* set all bytes to 0 */
  1559.     }
  1560.     outpw(SEQUENCER, 0x0100);   /* synchronous reset */
  1561.     outp(MISCOUT, 0xE7);        /* use 28 mhz dot clock */
  1562.     outpw(SEQUENCER, 0x0300);   /* restart sequencer */
  1563.     outp(CRTC, 0x11);        /* ctrl register 11, please */
  1564.     outp(CRTC+1, inp(CRTC+1) & 0x7f); /* write-prot cr0-7 */
  1565.  
  1566.     for (i = 0; i < 17; i++)    /* write CRTC register array */
  1567.         outpw(CRTC, vptbl[i]);
  1568.     }
  1569.  
  1570.     if (PaletteOption == HICOLOR && whichvga == TSENG4) {
  1571.     if ((int)inr.h.al == 0x78)    /* if it was mode 78 */
  1572.        inr.x.bx = 0x2F;        /* make it 2F... */
  1573.     else
  1574.        inr.x.bx = (unsigned int)inr.h.al;
  1575.     inr.x.ax = 0x10F0;
  1576.     int86(0x10, &inr, &inr);    /* Go from 256 color to 32K color mode */
  1577.     r_mask = g_mask = b_mask = 0xF8;
  1578.     r_shift = 7;
  1579.     g_shift = 2;
  1580.     b_shift = 3;
  1581.     svga_yincr <<= 1;
  1582.     }
  1583.  
  1584.     if (whichvga != ATIXL && PaletteOption != HICOLOR && PaletteOption != FULLCOLOR)
  1585.     palette_init();  /* if we get here it has a normal 256 color palette DAC */
  1586.  
  1587.     if (whichvga == CHIPSTECH) {    /* (not sure why this is necessary) */
  1588.     outpw(0x46E8, 0x001E);        /* put chip in setup mode */
  1589.     outpw(0x103, 0x0080);        /* enable extended registers */
  1590.     outpw(0x46E8, 0x000E);        /* take chip out of setup mode */
  1591.     outp(0x3D6, 0x10);
  1592.     }
  1593.  
  1594. exit_point:                /* we get here if there is no palette to initialize */
  1595.     if (whichvga == VESA && vesamode == 0x13) {
  1596.     bpp = 8;
  1597.     svga_height = 200;
  1598.     svga_width = 320;
  1599. /*    svga_yincr = 320; */
  1600.     }
  1601.     if (screen_height <= svga_height)
  1602.     y_off = (svga_height - screen_height)/2;
  1603.     else
  1604.     Height_Adjust = (DBL)screen_height / (DBL)svga_height;
  1605.     if (screen_width <= svga_width)
  1606.     x_off = (svga_width - screen_width)/2;
  1607.     else
  1608.     Width_Adjust = (DBL)screen_width / (DBL)svga_width;
  1609.  
  1610.     box(0, 0, width-1, height-1);
  1611.     /* Draw a box around the viewport, if defined */
  1612.     if(First_Column > 1 || Last_Column < width ||
  1613.      First_Line > 1 || Last_Line < height)
  1614.     box (First_Column, First_Line, Last_Column-1, Last_Line-1);
  1615.  
  1616. #if defined(DOS16RM)
  1617.     for (u=0; u < 257; u++)
  1618.     answer[u] = save[u];
  1619. #endif
  1620. #ifdef _INTELC32_
  1621.     _dos_setvect(0x10, prev_int10);      /* Restore previous handler */
  1622.     _dos_freemem((unsigned) answer);      /* Free DOS buffer */
  1623. #endif
  1624.     return;
  1625. }
  1626.  
  1627.  
  1628. int AutodetectVGA()          /* Autodetect (S)VGA Adapter Type */
  1629.     {
  1630.     unsigned char _far *biosptr;
  1631.     unsigned char tmp_byte;
  1632.     unsigned int tmp_word;
  1633.     unsigned int retval;
  1634.     union REGS inr, outr;
  1635. #ifdef GCCDOS
  1636.     _go32_dpmi_registers rdp;
  1637. #endif
  1638.     struct SREGS segs;
  1639.  
  1640. #if !defined(DOS386) && !defined(_INTELC32_) && !defined(__386__) && !defined(GCCDOS)
  1641.     if (tiga_set(CD_OPEN) >= 0) /* Try initializing HGWS/TIGA Adapter */
  1642.     {
  1643.     get_config(&config);
  1644.     vga_512K = TRUE;    /* All True-Color Adapters are > 512K! */
  1645.     if ((config.mode.disp_vres == 640) && (config.mode.disp_psize == 16) == TRUE)
  1646.         return(TIGA_16);
  1647.     if ((config.mode.disp_vres == 480) && (config.mode.disp_hres == 512) == TRUE)
  1648.         return(TIGA_24);
  1649.     if ((config.mode.disp_hres == 640) && (config.mode.disp_psize == 32) == TRUE)
  1650.         return(TRUE_640);
  1651.     if ((config.mode.disp_vres == 600) && (config.mode.disp_hres == 800) == TRUE)
  1652.         return(TRUE_800);
  1653.     return(TRUE_1024);
  1654.     }
  1655. #endif
  1656.  
  1657.     TGAHandle = open("TARGPLUS", O_RDWR | O_BINARY );   /* try equivalent to TARGA+ "GraphInit() call */
  1658.     if (TGAHandle != -1)                /* if open attempt was successful... */
  1659.     {
  1660.     close(TGAHandle);                /* close it up again */
  1661.     return(TARGA);                    /* and say we detected a TARGA+ card */
  1662.     }
  1663.  
  1664. #ifdef GCCDOS
  1665.   rdp.x.ax = 0x4f00;
  1666. #else
  1667.     inr.x.ax = 0x4F00;            /* Test for VESA Adapter */
  1668. #endif
  1669. #ifdef _INTELC32_
  1670.     inr.w.edi = (unsigned)answer;
  1671.     int86(0x10, &inr, &outr);
  1672. #else
  1673. #ifdef GCCDOS
  1674.         buff=_go32_info_block.linear_address_of_transfer_buffer;
  1675.         memset(&rdp,0,sizeof(rdp));
  1676.         rdp.x.di = buff & 0xf;
  1677.         rdp.x.es= buff >> 4;        /* deposit results here */
  1678.         _go32_dpmi_simulate_int(0x10,&rdp);
  1679.         dosmemget(buff,256,answer);
  1680. #else
  1681. #ifdef DOS386
  1682.     inr.x.di = real_buf[0];        /* deposit results here */
  1683.     segread(&segs);            /* get our DS, etc. */
  1684.     segs.es = real_buf[1];        /* get segment of answer */
  1685.     int86x_real(0x10, &inr, &outr, &segs);
  1686.     for(tmp_word=0; tmp_word<sizeof(answer); tmp_word++)
  1687.     answer[tmp_word] = real_ptr[tmp_word];
  1688. #else
  1689. #ifdef DOS16RM
  1690.     inr.x.di = 0x580;            /* deposit results here */
  1691.     segs.es = 0;
  1692.     int86x(0x10, &inr, &outr, &segs);
  1693. #else
  1694. /* CCP - Added watcom section */
  1695. #ifdef __WATCOMC__
  1696. #ifdef __386__
  1697.     memset(&RMI, 0, sizeof(RMI));    /* Test for VESA Adapter */
  1698.     RMI.EAX = 0x4F00;            /* Call function 0 to get VGA info */
  1699.     RMI.ES = D32RealSeg(answer);    /* put DOS seg:off of answer into es:di */
  1700.     RMI.EDI = D32RealOff(answer);
  1701.  
  1702.     segread(&segs);            /* init our selectors */
  1703.     inr.x.ax = 0x0300;
  1704.     inr.x.bx = 0x10;
  1705.     inr.x.cx = 0;
  1706.     segs.es = FP_SEG(&RMI);        /* get segment of rmi */
  1707.     inr.x.di = FP_OFF(&RMI);        /* deposit results here */
  1708.     int86x(0x31, &inr, &outr, &segs);
  1709.     outr.x.ax = RMI.EAX;        /* for code below */
  1710. #endif
  1711. /* CCP - End */
  1712. #else
  1713.     segread(&segs);            /* get our DS, etc. */
  1714.     inr.x.di = FP_OFF(answer);        /* deposit results here */
  1715.     segread(&segs);            /* get our DS, etc. */
  1716.     segs.es = FP_SEG(answer);        /* get segment of answer */
  1717.     int86x(0x10, &inr, &outr, &segs);    /* BIOS adapter identify call */
  1718. #endif
  1719. #endif
  1720. #endif
  1721. #endif
  1722. #endif
  1723.  
  1724. #ifdef GCCDOS
  1725.     if (rdp.x.ax == 0x004f &&
  1726. #else
  1727.     if (outr.x.ax == 0x004F &&
  1728. #endif
  1729.      answer[0] == 'V' && answer[1] == 'E' &&
  1730.         answer[2] == 'S' && answer[3] == 'A') {
  1731.     vga_512K = TRUE;         /* assume all VESA's have >= 512K */
  1732.     return (VESA);
  1733.     }
  1734.  
  1735. #ifdef DOS386
  1736.     biosptr = MK_FP(_x386_zero_base_selector, 0x000C0040);
  1737. #else
  1738. #ifdef DOS16RM
  1739.     biosptr = (unsigned char *)D16SegAbsolute(0xC0040, 16);
  1740. #else
  1741.     biosptr = (unsigned char *)MK_FP(0xC000, 0x0040); /* Test for ATI Wonder */
  1742. #endif
  1743. #endif
  1744.  
  1745.     if (*biosptr == '3' && *(biosptr + 1) == '1')
  1746.     {
  1747.     _disable();            /* Disable system interrupts */
  1748.     outp(0x1CE, 0xBB);
  1749.     if (inp(0x1CD) & 0x20)
  1750.         vga_512K = TRUE;
  1751.     _enable();            /* Re-enable system interrupts */
  1752. #ifdef DOS16RM
  1753.     D16SegCancel((void *)biosptr);
  1754. #endif
  1755.     return (ATIVGA);
  1756.     }
  1757.     inr.x.ax = 0x7000;            /* Test for Everex &| Trident */
  1758.     inr.x.bx = 0;
  1759.  
  1760.     CLD;
  1761.  
  1762.     int86(0x10, &inr, &outr);
  1763.     if (outr.h.al == 0x70)
  1764.     {
  1765.     if (outr.h.ch & 0xC0)
  1766.         vga_512K = TRUE;
  1767.     outr.x.dx &= 0xFFF0;
  1768.     if (outr.x.dx == 0x6780)
  1769.         {
  1770.         printf("\nT6780\n");
  1771.         return (TRIDENT);
  1772.         }
  1773.     if (outr.x.dx == 0x2360)
  1774.         {
  1775.         printf("\nT2360\n");
  1776.         return (TRIDENT);
  1777.         }
  1778.     if (outr.x.dx == 0x6730)    /* EVGA? (No BIOS Page Fn.) */
  1779.         {
  1780.         printf("\nE6730\n");
  1781.         return (EVEREX);
  1782.         }
  1783.     printf("\nE0000\n");
  1784.     return (EVEREX);    /* Newer board with fetchable bankswitch */
  1785.     }
  1786.     outp(0x3C4, 0x0B);            /* Test for Trident */
  1787.     tmp_byte = (unsigned char) inp(0x3C5);
  1788.     if ((tmp_byte > 1) && (tmp_byte < 0x10))
  1789.     {
  1790.     vga_512K = TRUE;
  1791.     printf("\nT0000\n");
  1792.     return (TRIDENT);
  1793.     }
  1794.     if (cirrus())            /* Test Video7 Vega VGA (Cirrus) */
  1795.     return (CIRRUS);
  1796.     inr.x.ax = 0x6F00;            /* Test for Video7 SVGA */
  1797.     inr.x.bx = 0;            /* note - Vega VGA (Cirrus) will */
  1798.  
  1799.     CLD;
  1800.  
  1801.     int86(0x10, &inr, &outr);        /* pass this test - test Cirrus 1st */
  1802.     if (outr.h.bh == 'V' && outr.h.bl == '7')
  1803.     {
  1804.     inr.x.ax = 0x6F07;
  1805.  
  1806.     CLD;
  1807.  
  1808.     int86(0x10, &inr, &outr);
  1809.     if ((outr.h.ah & 0x7F) > 1)
  1810.         vga_512K = TRUE;
  1811.     return (VIDEO7);
  1812.     }
  1813.     outp(0x3CE, 9);            /* Test for Paradise */
  1814.     if (!inp(0x3CF))
  1815.     {
  1816.     outpw(0x3CE, 0x050F);        /* Turn off write protect on regs */
  1817.     if (chkbank(0,1))        /* if bank 0 and 1 same not para. */
  1818.         {                /* FALSE == banks same... (C) */
  1819.         if (chkbank(0, 64))     /* if bank 0 and 64 same only 256K */
  1820.         vga_512K = TRUE;
  1821.  
  1822.         retval = PARADISE;
  1823. #ifdef DOS16RM
  1824.         biosptr = (unsigned char *)D16SegAbsolute(0xC0039, 16);
  1825.         if ((*biosptr == '1') && (*biosptr+1 == '6')) /* p/n 003116 */
  1826.         retval = VDC600;    /* a real Paradise is p/n 003145 */
  1827.         D16SegCancel((void *)biosptr);
  1828. #else
  1829.         biosptr = (unsigned char *)MK_FP(0xC000, 0x0039);/* Test for AT&T VDC600 */
  1830.         if ((*biosptr == '1') && (*biosptr+1 == '6')) /* p/n 003116 */
  1831.         retval = VDC600;    /* a real Paradise is p/n 003145 */
  1832. #endif
  1833.         return (retval);
  1834.         }
  1835.     }
  1836.     inr.x.ax = 0x5F00;            /* Test for Chips & Tech */
  1837.     inr.x.bx = 0;
  1838.  
  1839.     CLD;
  1840.  
  1841.     int86(0x10, &inr, &outr);
  1842.     if (outr.h.al == 0x5F)
  1843.     {
  1844.     if (outr.h.bh >= 1)
  1845.         vga_512K = TRUE;
  1846.     return (CHIPSTECH);
  1847.     }
  1848.     outp(0x3D4, 0x33);            /* Test for Tseng 4000 or 3000 Chip */
  1849.     tmp_word = (unsigned int) inp(0x3D5) << 8;
  1850.     outpw(0x3D4, 0x0A33);
  1851.     outp(0x3D4, 0x33);
  1852.     retval = BASIC_VGA;
  1853.     if ((inp(0x3D5) & 0x0F) == 0x0A)
  1854.     {
  1855.     outpw(0x3D4, 0x0533);
  1856.     outp(0x3D4, 0x33);
  1857.     if ((inp(0x3D5) & 0x0F) == 0x05)
  1858.         {
  1859.         retval = TSENG4;
  1860.         outpw(0x3D4, tmp_word | 0x33);
  1861.         outp(0x3D4, 0x37);
  1862.         if ((inp(0x3D5) & 0x0A) == 0x0A)
  1863.         vga_512K = TRUE;
  1864.         outp(0x3BF, 0x03);        /* Enable access to extended regs */
  1865.         outp(0x3D8, 0xA0);
  1866.         outp(0x3D8, 0x29);        /* Enable mapping register access */
  1867.         outp(0x3D8, 0xA0);
  1868.         }
  1869.     }
  1870.     tmp_byte = (unsigned char) inp(0x3CD);    /* save bank switch reg */
  1871.     outp(0x3CD, 0xAA);                /* test register w/ 0xAA */
  1872.     if (inp(0x3CD) == 0xAA)
  1873.     {
  1874.     outp(0x3CD, 0x55);            /* test register w/ 0x55 */
  1875.     if (inp(0x3CD) == 0x55)
  1876.         {
  1877.         outp(0x3CD, tmp_byte);        /* restore bank switch reg */
  1878.         if (retval != TSENG4)        /* yep, it's a Tseng... */
  1879.         retval = TSENG3;
  1880.         vga_512K = TRUE;
  1881.         return (retval);
  1882.         }
  1883.     }
  1884.     outpw(0x3CE, 0x200F);            /* Test for Ahead A or B chipsets */
  1885.     tmp_byte = (unsigned char) inp(0x3CF);
  1886.     if (tmp_byte == 0x21)
  1887.     {
  1888.     vga_512K = TRUE;            /* Assume all Ahead's have 512K... */
  1889.     return (AHEADB);
  1890.     }
  1891.     if (tmp_byte == 0x20)
  1892.     {
  1893.     vga_512K = TRUE;
  1894.     return (AHEADA);
  1895.     }
  1896.     if ((inp(0x3DE) & 0xE0) == 0x60)         /* Test for Oak Tech OTI-067 */
  1897.     {
  1898.     outp(0x3DE, 0x0D);
  1899.     if (inp(0x3DF) & 0x80)
  1900.         vga_512K = TRUE;
  1901.     return(OAKTECH);
  1902.     }
  1903.     return (BASIC_VGA);              /* Return 1 if Unknown/BASIC_VGA */
  1904.     }
  1905.  
  1906. int cirrus()                     /* Test for presence of Cirrus VGA Chip */
  1907.     {
  1908.     unsigned char tmp_byte;
  1909.     unsigned int crc_word, tmp_word;
  1910.     int retcode = FALSE;
  1911.  
  1912.     outp(0x3D4, 0x0C);                /* assume 3Dx addressing, scrn A start addr hi */
  1913.     crc_word = (unsigned int) inp(0x3D5) << 8;    /* save the crc */
  1914.     outp(0x3D5, 0);                /* clear the crc */
  1915.     outp(0x3D4, 0x1F);                /* Eagle ID register */
  1916.     tmp_byte = (unsigned char) inp(0x3D5);    /* nybble swap "register" */
  1917.     tmp_word = (((tmp_byte & 0x0F) << 4) | ((tmp_byte & 0xf0) >> 4)) << 8;
  1918.     outpw(0x3C4, tmp_word | 0x06);        /* disable extensions */
  1919.     if (!inp(0x3C5))
  1920.     {
  1921.     tmp_word = (unsigned int) tmp_byte << 8;
  1922.     outpw(0x3C4, tmp_word | 0x06);        /* re-enable extensions */
  1923.     if (inp(0x3C5) == 1)
  1924.         retcode = TRUE;
  1925.     }
  1926.     outpw(0x3D5, crc_word | 0x0c);        /* restore the crc */
  1927.     return (retcode);
  1928.     }
  1929.  
  1930. int chkbank(bank0, bank1)            /* Paradise SVGA specific stuff */
  1931.    unsigned int bank0, bank1;            /* returns TRUE if banks are different RAM */
  1932.    {
  1933.    static unsigned int value = 0x1234;
  1934.    unsigned int _far *fp;
  1935.    unsigned int temp;
  1936.    unsigned int oldval0, oldval1;
  1937.  
  1938. #ifdef DOS386                    /* Point out into display RAM */
  1939.    fp = MK_FP(_x386_zero_base_selector, 0xB8000);
  1940. #else
  1941.    fp = (unsigned int *)MK_FP(0xB800, 0);    /* Point out into display RAM */
  1942. #endif
  1943.  
  1944.    outp(0x3CE, 9);
  1945.    outp(0x3CF, bank0);                /* save prior video data and write test values */
  1946.    oldval0 = *fp;
  1947.    *fp ^= value;
  1948.    if (*fp != (oldval0 ^ value)) {
  1949.       *fp = oldval0;
  1950.       return FALSE;                /* No RAM there at all -- can't be 512K */
  1951.       }
  1952.  
  1953.    outp(0x3CE, 9);
  1954.    outp(0x3CF, bank1);                /* save prior video data and write test values */
  1955.    oldval1 = *fp;
  1956.    *fp ^= value;
  1957.    if (*fp != (oldval1 ^ value)) {
  1958.       *fp = oldval1;
  1959.       outp(0x3CE, 9);
  1960.       outp(0x3CF, bank0);
  1961.       *fp = oldval0;
  1962.       return FALSE;                 /* No RAM there at all -- can't be 512K */
  1963.       }
  1964.    if (*fp != oldval0) {
  1965.       *fp = oldval1;
  1966.       outp(0x3CE, 9);
  1967.       outp(0x3CF, bank0);
  1968.       *fp = oldval0;
  1969.       return TRUE;                  /* pages cannot be the same RAM */
  1970.       }
  1971.  
  1972.    outp(0x3CE, 9);
  1973.    outp(0x3CF, bank0);
  1974.    temp = *fp;
  1975.    outp(0x3CE, 9);
  1976.    outp(0x3CF, bank1);
  1977.    *fp = oldval1;
  1978.    outp(0x3CE, 9);
  1979.    outp(0x3CF, bank0);
  1980.    *fp = oldval0;
  1981.  
  1982.    if (temp == oldval0)
  1983.       return FALSE;                  /* pages are the same RAM */
  1984.    else
  1985.       return TRUE;                  /* independent values, so not same RAM */
  1986.    }
  1987.  
  1988. void atiplot(x, y, r, g, b)             /* ATI VGA Wonder XL 32K color display plot */
  1989. int x, y, r, g, b;
  1990. {
  1991.    char plane=0;
  1992.    unsigned offset, tmp_word;
  1993.    unsigned long address;
  1994.    unsigned short _far *fp;
  1995.  
  1996.    r/=8;
  1997.    g/=8;
  1998.    b/=8;
  1999.    address = y * 1280L + x * 2L;
  2000.    offset = (unsigned)(address % 65536L);
  2001.    plane = (char)(address / 65536L);
  2002.    _disable();
  2003.  
  2004.    outp(0x1CE, 0xB2);               /* NOTE: this used to be the atibank() funct. - AAC */
  2005.    tmp_word = (unsigned int)((plane << 1) | (inp(0x1CF) & 0xE1));
  2006.    outpw(0x1CE, (tmp_word << 8) | 0x00B2);
  2007.  
  2008. #ifdef DOS386
  2009.    fp = MK_FP(_x386_zero_base_selector, 0xA0000 + offset);
  2010. #else
  2011. #ifdef DOS16RM
  2012.    fp = (unsigned short *)(display_base + offset);
  2013. #else
  2014.    fp = (unsigned short *)MK_FP(0xA000, offset);
  2015. #endif
  2016. #endif
  2017.  
  2018.    *fp = (unsigned short)(r * 1024 + g * 32 + b);
  2019.    _enable();
  2020.    return;
  2021. }
  2022.  
  2023. void SetTGARegs(cmd, read, r, s)    /* Setup TARGA+ Register Array Subroutine */
  2024. int cmd;                /* Command number */
  2025. int read;                /* 1 if read, 0 if write */
  2026. union REGS *r;                /* accumulator registers */
  2027. struct SREGS *s;            /* segment registers */
  2028. {
  2029.     if (read)
  2030. #ifdef GCCDOS
  2031.     r->x.ax = 0x440A;        /* GCCFIX will make this an IOCTL Read */
  2032. #else
  2033.     r->x.ax = 0x4402;        /* set up IOCTL Read */
  2034. #endif
  2035.     else
  2036. #ifdef GCCDOS
  2037.     r->x.ax = 0x440B;        /* GCCFIX will make this an IOCTL Write */
  2038. #else
  2039.     r->x.ax = 0x4403;        /* set up IOCTL Write */
  2040. #endif
  2041.     r->x.bx = TGAHandle;        /* TARGA device handle */
  2042.     r->x.cx = sizeof(TGACommand);    /* read/write a whole cmd struct */
  2043. #ifdef GCCDOS
  2044.     r->x.dx = c_val;            /* real mode offset of Command structure */
  2045. #else
  2046.     r->x.dx = (unsigned short) FP_OFF(command);     /* Address of Command structure */
  2047.     s->ds = (unsigned short) FP_SEG(command);
  2048. #endif
  2049. #ifdef DEBUG_VIDEO
  2050.        if (!diaged)
  2051.      {
  2052.        diaged = TRUE;
  2053.        printf(" Sizeof TGACommand = %d, command = %p, dx = %08lX, ds = %04X\n", r->x.cx, command, r->x.dx, s->ds);
  2054.      }
  2055. #endif
  2056.     command->IOCmd = cmd;        /* set current I/O command */
  2057.     command->IOStrucSiz = 260;        /* size in bytes of sizeof(TGARegs) = unsigned short [130] */
  2058. }
  2059.  
  2060.  
  2061. #if defined( DOS386 )
  2062. void setmany(palbuf, start, count)
  2063. unsigned char palbuf[256][3];
  2064. int start, count;
  2065. {
  2066.    unsigned char _far *fp;
  2067.    union REGS regs;
  2068.    struct SREGS sregs;
  2069.    unsigned i;
  2070.  
  2071.    /* Put the contents of the new palette into real memory, the only
  2072.       place I know that won't impact things is the video RAM. */
  2073.    fp = MK_FP(_x386_zero_base_selector, 0xA0000);
  2074.    for (i=start;i<start+count;i++) {
  2075.       fp[3*(i-start)  ] = palbuf[i][0];
  2076.       fp[3*(i-start)+1] = palbuf[i][1];
  2077.       fp[3*(i-start)+2] = palbuf[i][2];
  2078.       }
  2079.  
  2080.    regs.x.ax = 0x1012;
  2081.    regs.x.bx = start;
  2082.    regs.x.cx = count;
  2083.    regs.x.dx = 0;
  2084.    segread(&sregs);
  2085.    sregs.es  = 0xA000;
  2086.    int86x_real(0x10, ®s, ®s, &sregs);
  2087.    /* Now clear off the values that got dumped into the video RAM */
  2088.    for (i=0;i<3*count; i++)
  2089.       *fp++ = 0;
  2090. }
  2091. #endif
  2092.  
  2093. void palette_init()        /* Fill VGA 256 color palette with colors! */
  2094.     {
  2095.     register unsigned m;
  2096.     unsigned r, g, b;
  2097.     register DBL hue, sat, val;
  2098. #ifdef DOS386
  2099.     unsigned char palbuf[256][3];
  2100. #endif
  2101.  
  2102.     if (PaletteOption == GREY)         /* B/W Video Mod */
  2103.     {
  2104.     for (m = 1; m < 64; m++)     /* for the 1st 64 colors... */
  2105.         set_palette_register (m, m, m, m); /* set m to rgb value */
  2106.     for (m = 64; m < 256; m++)     /* for the remaining, at full value */
  2107.         set_palette_register (m, 63, 63, 63);
  2108.     return;
  2109.     }
  2110.     if (PaletteOption == P_332) /* 332 Video Mod */
  2111.     {
  2112.         for (r=0;r<8;r++)
  2113.             for (g=0;g<8;g++)
  2114.                 for (b=0;b<4;b++) {
  2115.                     m = (r * 32 + g * 4 + b);
  2116. #ifdef DOS386
  2117.             palbuf[m][0] = r * 9;
  2118.             palbuf[m][1] = g * 9;
  2119.             palbuf[m][2] = b * 21;
  2120. #else
  2121.             set_palette_register(m, r * 9, g * 9, b * 21);
  2122. #endif
  2123.                 }
  2124. #ifdef DOS386
  2125. setmany(palbuf, 0, 256);
  2126. #endif
  2127.         return;
  2128.     }
  2129.  
  2130.     /* otherwise, use the classic HSV palette scheme */
  2131.  
  2132.     set_palette_register(0, 0, 0, 0);    /* make palette register 0 black */
  2133.  
  2134.     set_palette_register(64, 63, 63, 63);   /* make palette register 64 white */
  2135.  
  2136.     set_palette_register(128, 31, 31, 31);  /* make register 128 dark grey */
  2137.  
  2138.     set_palette_register(192, 48, 48, 48);  /* make register 192 lite grey */
  2139.  
  2140.     for (m = 1; m < 64; m++)            /* for the 1st 64 colors... */
  2141.     {
  2142.     sat = 0.5;                /* start with the saturation and intensity low */
  2143.     val = 0.5;
  2144.     hue = 360.0 * ((DBL)(m)) / 64.0;    /* normalize to 360 */
  2145.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  2146.     set_palette_register (m, r, g, b);  /* set m to rgb value */
  2147.  
  2148.     sat = 1.0;                /* high saturation and half intensity (shades) */
  2149.     val = 0.50;
  2150.     hue = 360.0 * ((DBL)(m)) / 64.0;    /* normalize to 360 */
  2151.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  2152.     set_palette_register (m + 64, r, g, b);  /* set m + 64 */
  2153.  
  2154.     sat = 0.5;                /* half saturation and high intensity (pastels) */
  2155.     val = 1.0;
  2156.  
  2157.     hue = 360.0 * ((DBL)(m)) / 64.0;    /* normalize to 360 */
  2158.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  2159.     set_palette_register (m + 128, r, g, b); /* set m + 128 */
  2160.  
  2161.     sat = 1.0;                /* normal full HSV set at full intensity */
  2162.     val = 1.0;
  2163.  
  2164.     hue = 360.0 * ((DBL)(m)) / 64.0;    /* normalize to 360 */
  2165.     hsv_to_rgb (hue, sat, val, &r, &g, &b);
  2166.     set_palette_register (m + 192, r, g, b); /* set m + 192 */
  2167.     }
  2168.     return;
  2169.     }
  2170.  
  2171.  
  2172. void display_finished ()
  2173.     {
  2174.     if (Options & PROMPTEXIT)
  2175.     {
  2176.     fprintf (stdout,"\007\007");    /* long beep */
  2177.     fflush (stdout);        /* make sure its heard */
  2178.     while(!kbhit())         /* wait for key hit */
  2179.        ;
  2180.     if (!getch())            /* get another if ext. scancode */
  2181.        getch();
  2182.     }
  2183.     }
  2184.  
  2185.  
  2186. void display_close()            /* setup to Text 80x25 (mode 3) */
  2187.     {
  2188.     union REGS regs;
  2189.     struct SREGS segs;
  2190.  
  2191. #ifdef __386__
  2192.     regs.x.ax = 0x0003;
  2193.     int86(0x10, ®s, ®s);
  2194. /* CCP - Use DPMI to free answer buffer */
  2195.     regs.x.ax = 0x0101;        /* DPMI free DOS memory */
  2196.     regs.x.dx = answerSel;       /* Descriptor (memory) to be freed */
  2197.     int86 (0x31, ®s, ®s);
  2198. /* CCP - End */
  2199. #else
  2200.     if (whichvga < TRUECOLOR) {
  2201.     regs.x.ax = 0x0003;
  2202.     int86(0x10, ®s, ®s);
  2203.     }
  2204.     else {      /* must be non-SVGA */
  2205. #if !defined(_INTELC32_) && !defined(GCCDOS) && !defined(DOS16RM) && !defined(DOS386)
  2206.     if (whichvga <= TRUE_1024)
  2207.         set_videomode(PREVIOUS, INIT);
  2208.     else
  2209. #endif
  2210.         if (whichvga <= TARGA) {
  2211. #ifdef DEBUG_VIDEO
  2212.            diaged = FALSE;
  2213.            printf("DIAG: SetTGARegs(0,0) -");
  2214. #endif
  2215.         SetTGARegs(0, 0, ®s, &segs);    /* equivalent to TARGA+ "WriteAll()" call */
  2216. #ifdef GCCDOS
  2217.         command->IORegsOff = (unsigned short)t_val;   /* real mode offset pointer to TGARegs structure */
  2218.         command->IORegsSeg = (unsigned short)ds_val;
  2219. #else
  2220.         command->IORegsOff = (unsigned short)FP_OFF(TGARegs);    /* pointer to structure */
  2221.         command->IORegsSeg = (unsigned short)FP_SEG(TGARegs);
  2222. #endif
  2223. #ifdef DEBUG_VIDEO
  2224.        printf("DIAG: command = %p, TGARegs = %p, IORegsOff = %04X, IORegsSeg = %04X\n", command, TGARegs, command->IORegsOff, command->IORegsSeg);
  2225. #endif
  2226. #ifdef DOS386
  2227.         int86x_real(0x21, ®s, ®s, &segs);
  2228. #else
  2229.         int86x(0x21, ®s, ®s, &segs);        /* call DOS - status of operation is !regs.x.cflag */
  2230. #endif
  2231.         close(TGAHandle);                /* close file channel to targap.sys driver */
  2232.         }
  2233.     }
  2234. #endif
  2235.  
  2236. #ifdef DOS16RM
  2237.     D16SegCancel(display_base);
  2238. #endif
  2239.     return;
  2240. }
  2241.  
  2242.  
  2243.   /* plot a single RGB pixel */
  2244. void display_plot (x, y, Red, Green, Blue)
  2245.    int x, y;
  2246.    unsigned char Red, Green, Blue;
  2247.    {
  2248.    union REGS inr;
  2249.    struct SREGS segs;
  2250.  
  2251.    register unsigned char color, svga_page;
  2252.    unsigned char _far *fp;
  2253.    unsigned int svga_word;
  2254.    unsigned long svga_loc, nsvga_loc, lcolor;
  2255.    DBL h, s, v, fx, fy;
  2256. #ifdef DITHERED
  2257.    int i, r, g, b, re, ge, be, ri, gi, bi;
  2258. #endif
  2259.  
  2260.    if (x == First_Column)           /* first pixel on this line? */
  2261.     {
  2262. #ifdef DITHERED
  2263. if (screen_width <= 2048) {
  2264.      for(i=0;(unsigned short)i < screen_width+2;i++)
  2265.         {
  2266.         r_err[(y+1)&1][i+x_off] = 0;
  2267.         g_err[(y+1)&1][i+x_off] = 0;
  2268.         b_err[(y+1)&1][i+x_off] = 0;
  2269.         }
  2270. }
  2271. #endif
  2272.     lastx = -1;        /* reset cache, make sure we do the 1st one */
  2273.     lasty = lastline;    /* set last line do to prior line */
  2274.     }
  2275.  
  2276.     y += y_off;
  2277.     x += x_off;
  2278.  
  2279.    /* Scaling factors precomputed per RHA in Height_Adjust or Width_Adjust */
  2280.  
  2281.    if (screen_height > svga_height)    /* auto-scale Y */
  2282.     {
  2283.     fy = (DBL)y / Height_Adjust;
  2284.     y = (int)fy;        /* scale y to svga_height */
  2285.     if (y <= lasty)     /* discard if repeated line */
  2286.         return;
  2287.     lastline = y;        /* save current working line */
  2288.     }
  2289.  
  2290.    if (screen_width > svga_width)        /* auto-scale X */
  2291.     {
  2292.     fx = (DBL)x / Width_Adjust;
  2293.     x = (int)fx;        /* scale x to svga_width */
  2294.     if (x <= lastx)     /* discard if repeated pixel */
  2295.         return;
  2296.     lastx = x;        /* save most recent pixel done */
  2297.     }
  2298.  
  2299.    if (whichvga == ATIXL)
  2300.     {
  2301.     atiplot(x, y, (int)Red, (int)Green, (int)Blue);
  2302.     return;
  2303.     }
  2304.  
  2305.     if (whichvga == TARGA)
  2306.     {
  2307. #ifdef DEBUG_VIDEO
  2308.     diaged = TRUE;      /* I have this particular diag turned off for now - AAC */
  2309. /*    printf("DIAG: SetTGARegs(2,0) -");      */
  2310. #endif
  2311.     SetTGARegs(2, 0, &inr, &segs);        /* equivalent to TARGA+ "PutPixel()" call */
  2312.     command->IOxi = x;
  2313.     command->IOyi = (svga_height - 1) - y;    /* the stupid-ass TARGA+ board is upside down!! */
  2314.     switch(TGARegs[4]) {            /* sense pixel depth */
  2315.     case 1:     /* 8 bits total */
  2316.         lcolor = (unsigned long)((int)(0.299 * (DBL)Red) + (int)(0.587 * (DBL)Green) + (int)(.114 * (DBL)Blue));
  2317.         break;
  2318.     case 2:     /* 16 bits total */
  2319.         lcolor = (unsigned long)(((int)Blue & 0x00f8) >> 3) + (unsigned long)(((int)Green & 0x00f8) << 2) + (unsigned long)(((int)Red & 0x00f8) << 7);
  2320.         break;
  2321.     case 4:     /* 32 (and 24) bits total */
  2322.         lcolor = ((unsigned long)Red << 16) + ((unsigned long)Green << 8) + (unsigned long)Blue;
  2323.         break;
  2324.     }
  2325.  
  2326. #if !defined(DOS16RM) && !defined(DOS386) && !defined(_INTELC32_) && !defined (__386__) && !defined(GCCDOS)
  2327.     command->IOcolor = lcolor;
  2328. #else
  2329.     command->IOcolorLo = (unsigned short)(lcolor);
  2330.     command->IOcolorHi = (unsigned short)((lcolor & 0xFFFF0000L) >> 16);
  2331. #endif
  2332. #ifdef DOS386
  2333.     int86x_real(0x21, &inr, &inr, &segs);
  2334. #else
  2335.     int86x(0x21, &inr, &inr, &segs);            /* call DOS to perform the pixel write */
  2336. #endif
  2337.     return;                         /* status of operation is !regs.x.cflag */
  2338.     }
  2339.  
  2340. #if !defined(DOS386) && !defined(_INTELC32_) && !defined(__386__) && !defined(GCCDOS)
  2341.    if (whichvga == TIGA_16)
  2342.     {
  2343.     set_bcolor(0);
  2344.     set_fcolor(((unsigned)Red << 10) + (Green << 5) + Blue);
  2345.     draw_point(x, y);
  2346.     return;
  2347.     }
  2348.  
  2349.    if (whichvga == TIGA_24 || whichvga == TRUE_640 || whichvga == TRUE_640 || whichvga == TRUE_1024)
  2350.     {
  2351.     hpt[0] = Green;
  2352.     hpt[1] = Red;
  2353.     hpt[2] = Blue;
  2354.     host2gsp(hptr, ((whichvga == TIGA_24) ? 0x4000L : 0x8000L) * y + ((long) x << 5), 3, 0);
  2355.     return;
  2356.     }
  2357. #endif
  2358.  
  2359.    if (PaletteOption == FULLCOLOR) {
  2360.     svga_loc = ((unsigned long)svga_yincr) * y + x * pixel_len;
  2361.     svga_page = (unsigned char)(svga_loc/gran);
  2362.     svga_loc %= gran;
  2363.     if (svga_page != cur_page) {
  2364.         cur_page = svga_page;
  2365.         if (whichvga == VESA)
  2366.         {
  2367.         inr.x.bx = map_code;        /* map code = 0 or 1 */
  2368.         inr.x.ax = 0x4F05;
  2369.         inr.x.dx = (unsigned int)svga_page;
  2370. #ifdef DOS386
  2371.         int86_real(0x10, &inr, &inr);
  2372. #else
  2373.         int86(0x10, &inr, &inr);
  2374. #endif
  2375.         }
  2376.         else if (whichvga == PARADISE24X) /* need to do special bank */
  2377.         {                  /* switching with Paradise */
  2378.         newbank();              /* chips. */
  2379.         }
  2380.         else
  2381.         {
  2382.         outp(0x3CD, (unsigned char)svga_page);
  2383.         }
  2384.     }
  2385.  
  2386. #ifdef DOS386
  2387.     fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)svga_loc);
  2388. #else
  2389. #ifdef DOS16RM
  2390.     fp = display_base + (unsigned int)svga_loc;
  2391. #else
  2392.     fp = (unsigned char *)MK_FP(0xA000, (unsigned int)svga_loc);
  2393. #endif
  2394. #endif
  2395.     if (svga_loc + 2 < gran) {          /* if pixel doesn't cross */
  2396.         fp[blue_ndx] = (unsigned char)Blue;   /* bank, draw all of it */
  2397.         fp[green_ndx] = (unsigned char)Green;
  2398.         fp[red_ndx] = (unsigned char)Red;
  2399.     }
  2400.     else {                      /* otherwise do bank      */
  2401.       cur_page++;                  /* switch for next bank */
  2402.       newbank();
  2403.       if (svga_loc+blue_ndx >= gran) {
  2404.           nsvga_loc = (svga_loc+blue_ndx) % gran;
  2405. #ifdef DOS386
  2406.     fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)nsvga_loc);
  2407. #else
  2408. #ifdef DOS16RM
  2409.     fp = display_base + (unsigned int)nsvga_loc;
  2410. #else
  2411.     fp = (unsigned char *)MK_FP(0xA000, (unsigned int)nsvga_loc);
  2412. #endif
  2413. #endif
  2414.           *fp = (unsigned char)Blue;
  2415.       }
  2416.       if (svga_loc+green_ndx >= gran) {
  2417.           nsvga_loc = (svga_loc+green_ndx) % gran;
  2418. #ifdef DOS386
  2419.     fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)nsvga_loc);
  2420. #else
  2421. #ifdef DOS16RM
  2422.     fp = display_base + (unsigned int)nsvga_loc;
  2423. #else
  2424.     fp = (unsigned char *)MK_FP(0xA000, (unsigned int)nsvga_loc);
  2425. #endif
  2426. #endif
  2427.           *fp = (unsigned char)Green;
  2428.       }
  2429.       if (svga_loc+red_ndx >= gran) {
  2430.           nsvga_loc = (svga_loc+red_ndx) % gran;
  2431. #ifdef DOS386
  2432.     fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)nsvga_loc);
  2433. #else
  2434. #ifdef DOS16RM
  2435.     fp = display_base + (unsigned int)nsvga_loc;
  2436. #else
  2437.     fp = (unsigned char *)MK_FP(0xA000, (unsigned int)nsvga_loc);
  2438. #endif
  2439. #endif
  2440.           *fp = (unsigned char)Red;
  2441.       }
  2442.     }
  2443.     return;
  2444.     }
  2445.     if (PaletteOption == HICOLOR) {
  2446.     svga_loc = ((unsigned long)svga_yincr) * y + (x << 1);
  2447.     svga_page = (unsigned char)(svga_loc/gran);
  2448.     svga_loc %= gran;
  2449.     if (svga_page != cur_page) {
  2450.         cur_page = svga_page;
  2451.         if (whichvga == VESA)
  2452.         {
  2453.         inr.x.bx = map_code;        /* map code = 0 or 1 */
  2454.         inr.x.ax = 0x4F05;
  2455.         inr.x.dx = (unsigned int)svga_page;
  2456. #ifdef DOS386
  2457.         int86_real(0x10, &inr, &inr);
  2458. #else
  2459.         int86(0x10, &inr, &inr);
  2460. #endif
  2461.         }
  2462.         else if (whichvga == PARADISE24X) /* need to do special bank */
  2463.         {                  /* switching with Paradise */
  2464.         newbank();              /* chips. */
  2465.         }
  2466.         else
  2467.         outp(0x3CD, (unsigned char)svga_page);
  2468.         }
  2469.  
  2470. #ifdef DOS386
  2471.     fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)svga_loc);
  2472. #else
  2473. #ifdef DOS16RM
  2474.     fp = display_base + (unsigned int)svga_loc;
  2475. #else
  2476.     fp = (unsigned char *)MK_FP(0xA000, (unsigned int)svga_loc);
  2477. #endif
  2478. #endif
  2479.  
  2480. #ifdef DITHERED
  2481. if (screen_width <= 2048) {
  2482.     r = ri = (int)Red + (int)r_err[y&1][x+1]/16;
  2483.     g = gi = (int)Green + (int)g_err[y&1][x+1]/16;
  2484.     b = bi = (int)Blue + (int)b_err[y&1][x+1]/16;
  2485.  
  2486.     if(ri > 255) ri = 255;
  2487.     if(gi > 255) gi = 255;
  2488.     if(bi > 255) bi = 255;
  2489.     if(ri < 0) ri = 0;
  2490.     if(gi < 0) gi = 0;
  2491.     if(bi < 0) bi = 0;
  2492.  
  2493.     ri &= r_mask;
  2494.     gi &= g_mask;
  2495.     bi &= b_mask;
  2496.  
  2497.     re = r - ri;
  2498.     ge = g - gi;
  2499.     be = b - bi;
  2500.  
  2501.     r_err[y&1][x+2] += (signed char)(7*re);
  2502.     r_err[y&1][x] += (signed char)re;
  2503.     r_err[(y+1)&1][x+1] += (signed char)(5*re);
  2504.     r_err[(y+1)&1][x+2] += (signed char)(3*re);
  2505.     g_err[y&1][x+2] += (signed char)(7*ge);
  2506.     g_err[y&1][x] += (signed char)ge;
  2507.     g_err[(y+1)&1][x+1] += (signed char)(5*ge);
  2508.     g_err[(y+1)&1][x+2] += (signed char)(3*ge);
  2509.     b_err[y&1][x+2] += (signed char)(7*be);
  2510.     b_err[y&1][x] += (signed char)be;
  2511.     b_err[(y+1)&1][x+1] += (signed char)(5*be);
  2512.     b_err[(y+1)&1][x+2] += (signed char)(3*be);
  2513.  
  2514.     *(unsigned short _far *)fp = (unsigned short)  /* stash 16-bit pixel */
  2515.         (((unsigned long)ri << r_shift) |
  2516.         ((unsigned long)gi << g_shift) |((unsigned long)bi >> b_shift));
  2517.     return;
  2518. }
  2519. else
  2520.     *(unsigned short _far *)fp = (unsigned short)  /* stash 16-bit pixel */
  2521.         (((unsigned long)(Red & r_mask) << r_shift) |
  2522.         ((unsigned long)(Green & g_mask) << g_shift) |
  2523.         ((unsigned long)(Blue & b_mask) >> b_shift));
  2524.     return;
  2525.  
  2526. #else
  2527.     *(unsigned short _far *)fp = (unsigned short)  /* stash 16-bit pixel */
  2528.         (((unsigned long)(Red & r_mask) << r_shift) |
  2529.         ((unsigned long)(Green & g_mask) << g_shift) |
  2530.         ((unsigned long)(Blue & b_mask) >> b_shift));
  2531.     return;
  2532. #endif
  2533.     }
  2534.  
  2535.     if (PaletteOption == GREY)              /* RGB are already set the same, so */
  2536.     color = (unsigned char)(Green >> 2);  /* really, any color will do... */
  2537.     else if (PaletteOption == P_332) {
  2538. #ifdef DITHERED
  2539. if (screen_width <= 2048) {
  2540.     r = (int)Red + (int)r_err[y&1][x+1];
  2541.     g = (int)Green + (int)g_err[y&1][x+1];
  2542.     b = (int)Blue + (int)b_err[y&1][x+1];
  2543.  
  2544.     ri = (r+18)/36;
  2545.     gi = (g+18)/36;
  2546.     bi = (b+42)/84;
  2547.  
  2548.     if (ri > 7)
  2549.         ri=7;
  2550.     if (gi > 7)
  2551.         gi=7;
  2552.     if (bi > 3)
  2553.         bi=3;
  2554.     if (ri < 0)
  2555.         ri=0;
  2556.     if (gi < 0)
  2557.         gi=0;
  2558.     if (bi < 0)
  2559.         bi=0;
  2560.  
  2561.     color = (unsigned char)(((ri<<5) + (gi<<2) + bi));
  2562.  
  2563.     re = r - ((255 * ri) / 7);
  2564.     ge = g - ((255 * gi) / 7);
  2565.     be = b - ((255 * bi) / 3);
  2566.  
  2567.     r_err[y&1][x+2] += (signed char)((7*re)/16);
  2568.     r_err[y&1][x] += (signed char)(re/16);
  2569.     r_err[(y+1)&1][x+1] += (signed char)((5*re)/16);
  2570.     r_err[(y+1)&1][x+2] += (signed char)((3*re)/16);
  2571.     g_err[y&1][x+2] += (signed char)((7*ge)/16);
  2572.     g_err[y&1][x] += (signed char)(ge/16);
  2573.     g_err[(y+1)&1][x+1] += (signed char)((5*ge)/16);
  2574.     g_err[(y+1)&1][x+2] += (signed char)((3*ge)/16);
  2575.     b_err[y&1][x+2] += (signed char)((7*be)/16);
  2576.     b_err[y&1][x] += (signed char)(be/16);
  2577.     b_err[(y+1)&1][x+1] += (signed char)((5*be)/16);
  2578.     b_err[(y+1)&1][x+2] += (signed char)((3*be)/16);
  2579. }
  2580. else
  2581.     color = ((Red & 0xE0) | ((Green & 0xE0) >> 3) | ((Blue & 0xC0) >> 6));
  2582. #else
  2583.     color = ((Red & 0xE0) | ((Green & 0xE0) >> 3) | ((Blue & 0xC0) >> 6));
  2584.  
  2585. #endif
  2586.     }
  2587.     else {  /* Translate RGB value to nearest of 256 palette Colors (by HSV) */
  2588.     rgb_to_hsv((unsigned)Red,(unsigned)Green,(unsigned)Blue, &h, &s, &v);
  2589.     if (s < 0.20) {       /* black or white if no saturation of color... */
  2590.         if (v < 0.25)
  2591.         color = 0;      /* black */
  2592.         else if (v > 0.8)
  2593.         color = 64;      /* white */
  2594.         else if (v > 0.5)
  2595.         color = 192;      /* lite grey */
  2596.         else
  2597.         color = 128;      /* dark grey */
  2598.     }
  2599.     else {
  2600.         color = (unsigned char) (64.0 * ((DBL)(h)) / 360.0);
  2601.  
  2602.         if (!color)
  2603.         color = 1;      /* avoid black, white or grey */
  2604.  
  2605.         if (color > 63)
  2606.         color = 63;      /* avoid same */
  2607.  
  2608.         if (v > 0.50)
  2609.         color |= 0x80;      /* colors 128-255 for high inten. */
  2610.  
  2611.         if (s > 0.50)      /* more than half saturated? */
  2612.         color |= 0x40;      /* color range 64-128 or 192-255 */
  2613.     }
  2614.     }
  2615.     switch (whichvga)          /* decide on (S)VGA bank switching scheme to use */
  2616.     {
  2617.        case BASIC_VGA:      /* none */
  2618.         svga_loc = svga_yincr * y + x;
  2619.         break;
  2620.  
  2621.        case MODE13x:      /* faked */
  2622.         svga_word = 1 << (x & 3);    /* form bit plane mask */
  2623.         svga_word = (svga_word << 8) | 2;
  2624.         outpw(SEQUENCER, svga_word);    /* tweak the sequencer */
  2625.         svga_loc = svga_yincr * y + (x >> 2);
  2626.         break;
  2627.  
  2628.        default:          /* actual bank switch for all SVGA cards */
  2629.         svga_loc=((unsigned long)svga_yincr) * y + x;
  2630.         svga_page=(unsigned char)(svga_loc/gran);
  2631.         svga_loc %= gran;
  2632.         if (cur_page != svga_page)    /* if not in correct bank */
  2633.         {
  2634.             cur_page = svga_page;    /* set new working bank */
  2635.             if (whichvga != VESA)
  2636.             {
  2637.             _disable();
  2638.             newbank();
  2639.             _enable();
  2640.         }
  2641.             else
  2642.             newbank();
  2643.         }
  2644.         break;
  2645.     }
  2646.  
  2647. #ifdef DOS386
  2648.    fp = MK_FP(_x386_zero_base_selector, 0xA0000 + (unsigned int)svga_loc);
  2649. #else
  2650. #ifdef DOS16RM
  2651.    fp = display_base + (unsigned int)svga_loc;
  2652. #else
  2653.    fp = (unsigned char *)MK_FP(0xA000, (unsigned int)svga_loc);
  2654. #endif
  2655. #endif
  2656.    *fp = color;     /* write normalized pixel color val to bitplane */
  2657.  
  2658.    return;
  2659.    }
  2660.  
  2661. void newbank()        /* Perform SVGA bank switch on demand - Voila! */
  2662. {
  2663.     register unsigned char tmp_byte, tmp_byte1;
  2664.     register unsigned int tmp_word;
  2665.     union REGS regs;
  2666.     static unsigned char xlateT3[] = {0x40, 0x49, 0x52, 0x5B, 0x64, 0x6D,
  2667.         0x76, 0x7F};
  2668.     static unsigned char xlateT4[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
  2669.         0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF};
  2670.  
  2671.  
  2672.     switch (whichvga)
  2673.     {
  2674.     case VDC600:            /* AT&T VDC 600 */
  2675.         tmp_byte = (unsigned char) (cur_page << 4); /* was >> 12... */
  2676.         outpw(0x03CE,0x050F);
  2677.         outp(0x03CE,0x09);
  2678.         outp(0x03CF, tmp_byte);
  2679.         break;
  2680.     case OAKTECH:            /* Oak Technology OTI-067 */
  2681.         tmp_byte = (unsigned char)(cur_page & 0x0F);
  2682.         outp(0x3DF, (tmp_byte << 4) | tmp_byte);
  2683.         break;
  2684.     case AHEADA:            /* Ahead Systems Ver A */
  2685.         outpw(0x3CE, 0x200F);    /* enable extended registers */
  2686.         tmp_byte = (unsigned char)(inp(0x3CC) & 0xDF);  /* bit 0 */
  2687.         if (cur_page & 1)
  2688.             tmp_byte |= 0x20;
  2689.         outp(0x3C2, tmp_byte);
  2690.         outp(0x3CF, 0);           /* bits 1, 2, 3 */
  2691.         tmp_word = (unsigned int)((cur_page >> 1 )|(inp(0x3D0) & 0xF8));
  2692.         outpw(0x3CF, tmp_word << 8);
  2693.         break;
  2694.     case AHEADB:            /* Ahead Systems Ver B */
  2695.         outpw(0x3CE, 0x200F);    /* enable extended registers */
  2696.         tmp_word = (unsigned int)((cur_page << 4) | cur_page);
  2697.         outpw(0x3CF, (tmp_word << 8) | 0x000D);
  2698.         break;
  2699.     case EVEREX:            /* Everex SVGA's */
  2700.         outp(0x3C4, 8);
  2701.         if (cur_page & 1)
  2702.          tmp_word = (unsigned int)(inp(0x3C5) | 0x80);
  2703.         else tmp_word = (unsigned int)(inp(0x3C5) & 0x7F);
  2704.         outpw(0x3C4, (tmp_word << 8) | 0x0008);
  2705.         tmp_byte = (unsigned char)(inp(0x3CC) & 0xDF);
  2706.         if (!(cur_page & 2))
  2707.          tmp_byte |= 0x20;
  2708.         outp(0x3C2, tmp_byte);
  2709.         break;
  2710.     case ATIVGA:            /* ATI VGA Wonder (and the XL) */
  2711.         outp(0x1CE, 0xB2);
  2712.         tmp_word = (unsigned int)((cur_page << 1) | (inp(0x1CF) & 0xE1));
  2713.         outpw(0x1CE, (tmp_word << 8) | 0x00B2);
  2714.         break;
  2715.     case TRIDENT:
  2716.         outp(0x3CE, 6);        /* set page size to 64K */
  2717.         tmp_word = (unsigned int)(inp(0x3CF) | 4) << 8;
  2718.         outpw(0x3CE, tmp_word | 0x0006);
  2719.         outp(0x3C4, 0x0b);        /* switch to BPS mode */
  2720.         inp(0x3C5);         /* dummy read?? */
  2721.         tmp_word = (unsigned int)(cur_page ^ 2) << 8;
  2722.         outpw(0x3C4, tmp_word | 0x000E);
  2723.         break;
  2724.     case VIDEO7:            /* Video-7 VRAM, FastRAM SVGA cards */
  2725.         tmp_byte1 = tmp_byte = (unsigned char)(cur_page & 0x0F);
  2726.         outpw(0x3C4, 0xEA06);
  2727.         tmp_word = (unsigned int)(tmp_byte & 1) << 8;
  2728.         outpw(0x3C4, tmp_word | 0x00F9);
  2729.         tmp_byte &= 0x0C;
  2730.         tmp_word = (unsigned int)((tmp_byte >> 2) | tmp_byte) << 8;
  2731.         outpw(0x3C4, tmp_word | 0x00F6);
  2732.         tmp_word |= (inp(0x3C5) & 0xF0) << 8;
  2733.         outpw(0x3C4, tmp_word | 0x00F6);
  2734.         tmp_byte = (unsigned char)((tmp_byte1 << 4) & 0x20);
  2735.         outp(0x3C2, (inp(0x3CC) & 0xDF) | tmp_byte);
  2736.         break;
  2737.     case CHIPSTECH:         /* Chips & Technology VGA Chip Set */
  2738.         outp(0x3D7, cur_page << 2); /* this is all that's necessary?? */
  2739.         break;
  2740.     case PARADISE24X:        /* Diamond Speedstar 24X  */
  2741.     case PARADISE:            /* Paradise, Professional, Plus */
  2742.         outpw(0x3CE, 0x050F);    /* turn off VGA reg. write protect */
  2743.         tmp_word = (unsigned int)(cur_page << 4) << 8;
  2744.         outpw(0x3CE, tmp_word | 0x0009);
  2745.         break;
  2746.     case TSENG3:            /* Tseng 3000 - Orchid, STB, etc. */
  2747.         outp(0x3CD, xlateT3[cur_page & 0x07]);
  2748.         break;
  2749.     case TSENG4:            /* Tseng 4000 - Orchid PD+, etc. */
  2750.         outp(0x3CD, xlateT4[cur_page & 0x0F]);
  2751.         break;
  2752.     case VESA:            /* VESA standard mode bank switch */
  2753.         regs.x.ax = 0x4F05;     /* VESA BIOS bank switch call */
  2754.         regs.x.dx = cur_page;
  2755.         regs.x.bx = map_code;    /* Map code 0 or 1? */
  2756. #ifdef DOS386
  2757.         int86_real(0x10, ®s, ®s);
  2758. #else
  2759.         int86(0x10, ®s, ®s);    /* Do the video BIOS interrupt */
  2760. #endif
  2761.     }
  2762.     return;
  2763. }
  2764.  
  2765. void set_palette_register (Val, Red, Green, Blue)
  2766.    unsigned Val;
  2767.    unsigned Red, Green, Blue;
  2768.    {
  2769.    union REGS Regs;
  2770.  
  2771.    Regs.x.ax = 0x1010;            /* Set one palette register function */
  2772.    Regs.x.bx = Val;            /* the palette register to set (color#)*/
  2773.    Regs.h.dh = (char)(Red & 0x3f);  /* set the gun values (6 bits ea.) */
  2774.    Regs.h.ch = (char)(Green & 0x3f);
  2775.    Regs.h.cl = (char)(Blue & 0x3f);
  2776.    int86(0x10, &Regs, &Regs);        /* Do the video interrupt */
  2777.    }
  2778.  
  2779. /* Conversion from Hue, Saturation, Value to Red, Green, and Blue and back */
  2780. /* From "Computer Graphics", Donald Hearn & M. Pauline Baker, p. 304 */
  2781.  
  2782. void hsv_to_rgb(hue, s, v, r, g, b)
  2783.    DBL hue, s, v;        /* hue (0.0-360.0) s and v from 0.0-1.0) */
  2784.    unsigned *r, *g, *b;     /* values from 0 to 63 */
  2785.    {
  2786.    register DBL i, f, p1, p2, p3;
  2787.    register DBL xh;
  2788.    register DBL nr, ng, nb;    /* rgb values of 0.0 - 1.0 */
  2789.  
  2790.    if (hue == 360.0)
  2791.       hue = 0.0;        /* (THIS LOOKS BACKWARDS BUT OK) */
  2792.  
  2793.    xh = hue / 60.0;        /* convert hue to be in 0,6    */
  2794.    i = floor(xh);        /* i = greatest integer <= h    */
  2795.    f = xh - i;            /* f = fractional part of h    */
  2796.    p1 = v * (1 - s);
  2797.    p2 = v * (1 - (s * f));
  2798.    p3 = v * (1 - (s * (1 - f)));
  2799.  
  2800.    switch ((int) i)
  2801.       {
  2802.       case 0:
  2803.      nr = v;
  2804.      ng = p3;
  2805.      nb = p1;
  2806.      break;
  2807.       case 1:
  2808.      nr = p2;
  2809.      ng = v;
  2810.      nb = p1;
  2811.      break;
  2812.       case 2:
  2813.      nr = p1;
  2814.      ng = v;
  2815.      nb = p3;
  2816.      break;
  2817.       case 3:
  2818.      nr = p1;
  2819.      ng = p2;
  2820.      nb = v;
  2821.      break;
  2822.       case 4:
  2823.      nr = p3;
  2824.      ng = p1;
  2825.      nb = v;
  2826.      break;
  2827.       case 5:
  2828.      nr = v;
  2829.      ng = p1;
  2830.      nb = p2;
  2831.      break;
  2832.       default:
  2833.      nr = ng = nb = 0;
  2834.     }
  2835.  
  2836.    *r = (unsigned)(nr * 63.0); /* Normalize the values to 63 */
  2837.    *g = (unsigned)(ng * 63.0);
  2838.    *b = (unsigned)(nb * 63.0);
  2839.  
  2840.    return;
  2841.    }
  2842.  
  2843.  
  2844. void rgb_to_hsv(r, g, b, h, s, v)
  2845.    unsigned r, g, b;
  2846.    DBL *h, *s, *v;
  2847.    {
  2848.    register DBL m, r1, g1, b1;
  2849.    register DBL nr, ng, nb;        /* rgb values of 0.0 - 1.0 */
  2850.    register DBL nh = 0.0, ns, nv;    /* hsv local values */
  2851.  
  2852.    nr = (DBL) r / 255.0;
  2853.    ng = (DBL) g / 255.0;
  2854.    nb = (DBL) b / 255.0;
  2855.  
  2856.    nv = max (nr, max (ng, nb));
  2857.    m = min (nr, min (ng, nb));
  2858.  
  2859.    if (nv != 0.0)         /* if no value, it's black! */
  2860.       ns = (nv - m) / nv;
  2861.    else
  2862.       ns = 0.0;          /* black = no colour saturation */
  2863.  
  2864.    if (ns == 0.0)         /* hue undefined if no saturation */
  2865.    {
  2866.       *h = 0.0;          /* return black level (?) */
  2867.       *s = 0.0;
  2868.       *v = nv;
  2869.       return;
  2870.    }
  2871.  
  2872.    r1 = (nv - nr) / (nv - m);     /* distance of color from red     */
  2873.    g1 = (nv - ng) / (nv - m);     /* distance of color from green */
  2874.    b1 = (nv - nb) / (nv - m);     /* distance of color from blue  */
  2875.  
  2876.    if (nv == nr)
  2877.    {
  2878.       if (m == ng)
  2879.      nh = 5. + b1;
  2880.       else
  2881.      nh = 1. - g1;
  2882.    }
  2883.  
  2884.    if (nv == ng)
  2885.       {
  2886.       if (m == nb)
  2887.      nh = 1. + r1;
  2888.       else
  2889.      nh = 3. - b1;
  2890.       }
  2891.  
  2892.    if (nv == nb)
  2893.       {
  2894.       if (m == nr)
  2895.      nh = 3. + g1;
  2896.       else
  2897.      nh = 5. - r1;
  2898.       }
  2899.  
  2900.    *h = nh * 60.0;      /* return h converted to degrees */
  2901.    *s = ns;
  2902.    *v = nv;
  2903.    return;
  2904.    }
  2905.  
  2906. void box(x1, y1, x2, y2)  /* RHA's draw a thin white box funct. */
  2907. int x1, y1, x2, y2;
  2908. {
  2909.    int i;
  2910.    for (i = x1+1; i < x2; i++)
  2911.    {
  2912.     lastx = -1;  lasty = -1; lastline = -1;
  2913.     display_plot(i, y1, 255, 255, 255);
  2914.     lastx = -1;  lasty = -1; lastline = -1;
  2915.     display_plot(i, y2, 255, 255, 255);
  2916.    }
  2917.    for (i = y1; i <= y2; i++)
  2918.    {
  2919.     lastx = -1;  lasty = -1; lastline = -1;
  2920.     display_plot(x1, i, 255, 255, 255);
  2921.     lastx = -1;  lasty = -1; lastline = -1;
  2922.     display_plot(x2, i, 255, 255, 255);
  2923.    }
  2924.    lastx = -1;
  2925.    lasty = -1;
  2926.    lastline = -1;
  2927.    return;
  2928. }
  2929.  
  2930. #if !__STDC__
  2931. #if !defined(__BORLANDC__) && !defined (__ZTC__) && !defined(__TURBOC__)
  2932.  /* BCC has srand but doesn't set __STDC__ same as Zortech */
  2933.  
  2934.  
  2935. /* ANSI Standard psuedo-random number generator */
  2936.  
  2937. int rand(void);
  2938. void srand(int);
  2939.  
  2940. static unsigned long int next = 1;
  2941.  
  2942. int rand()
  2943.    {
  2944.    next = next * 1103515245L + 12345L;
  2945.    return ((int) (next / 0x10000L) & 0x7FFF);
  2946.    }
  2947.  
  2948. void srand(seed)
  2949.    int seed;
  2950.    {
  2951.    next = (unsigned long int)seed;
  2952.    }
  2953.  
  2954. #endif
  2955. #endif
  2956.  
  2957.  
  2958. /* Math Error exception struct format:
  2959.     int type;        - exception type - see below
  2960.     char _far *name;    - name of function where error occured
  2961.     long double arg1;    - first argument to function
  2962.     long double arg2;    - second argument (if any) to function
  2963.     long double retval;    - value to be returned by function
  2964. */
  2965.  
  2966. #ifdef __WATCOMC__
  2967. #define EDOM    7    /* MSC is 33 */
  2968. #define ERANGE    8    /* MSC is 34 */
  2969.  
  2970. int matherr(e)
  2971.    struct exception *e;
  2972. #else
  2973. #ifdef GCCDOS
  2974. int matherr(e)
  2975.    struct libm_exception *e;
  2976. #else
  2977. int _cdecl matherr(e)
  2978.    struct exception *e;
  2979. #endif
  2980. #endif
  2981.    {
  2982.    if (Options & DEBUGGING) {
  2983.       /* Since we are just making pictures, not keeping nuclear power under
  2984.      control - it really isn't important if there is a minor math problem.
  2985.      This routine traps and ignores them.  Note: the most common one is
  2986.      a DOMAIN error coming out of "acos". */
  2987.       switch (e->type) {
  2988.      case DOMAIN   : printf("DOMAIN error in '%s'\n", e->name); break;
  2989.      case SING     : printf("SING   error in '%s'\n", e->name); break;
  2990.      case OVERFLOW : printf("OVERFLOW error in '%s'\n", e->name); break;
  2991.      case UNDERFLOW: printf("UNDERFLOW error in '%s'\n", e->name); break;
  2992.      case TLOSS    : printf("TLOSS error in '%s'\n", e->name); break;
  2993.      case PLOSS    : printf("PLOSS error in '%s'\n", e->name); break;
  2994. #ifdef EDOM
  2995.      case EDOM     : printf("EDOM error in '%s'\n", e->name); break;
  2996. #endif
  2997. #ifdef ERANGE
  2998.      case ERANGE   : printf("ERANGE error in '%s'\n", e->name); break;
  2999. #endif
  3000.      default       : printf("Unknown math error in '%s'\n",e->name);break;
  3001.      }
  3002.       }
  3003.    return (1);    /* Indicate the math error was corrected... */
  3004.    }
  3005.  
  3006. #ifdef _INTELC32_
  3007.  
  3008. void int10 ( void )        /* User Int 10h Protected-Mode Interrupt Handler */
  3009.    {
  3010.    _XSTACK *ebp;        /* Stack frame passed to real-mode handler */
  3011.    _XSTACK *ebx;        /* Stack frame returned to interrupted process */
  3012.  
  3013.    ebp = (_XSTACK *) _get_stk_frame();        /* Get stack frame address */
  3014.    if ((ebp->eax & 0x0000FFFE) != 0x4F00) { /* Check for function = 4F00/1h */
  3015.       (*prev_int10)();                /* Call previous handler? */
  3016.       return;
  3017.       }
  3018.  
  3019.    if ((ebp->edi & 0xFFF00000) != 0) {
  3020.       ebx = (_XSTACK *) _get_ebx();/* Get return stack frame address */
  3021.       ebx->eax = 0x0000104F;       /* Return code of 0x10=Extended mem err */
  3022.       ebp->flg |= _FLAG_CARRY;       /* Set carry flag to indicate an error */
  3023.       ebp->opts |= _STK_NOINT;       /* Bypass real-mode handler */
  3024.       return;
  3025.       }
  3026.  
  3027.    /* Put the segment value from the physical address in the ES.  */
  3028.    ebp->es = (short)((ebp->edi & 0x000FFFF0) >> 4);
  3029.    ebp->edi &= 0x0000000F;       /* Offset value from physical address */
  3030.    ebp->opts = 0;           /* Pass to real-mode handler */
  3031.    return;
  3032.    }
  3033.  
  3034. #endif
  3035.  
  3036. void print_ibm_credits()
  3037.   {
  3038.   fprintf (stderr," \n");
  3039.  
  3040.   fprintf (stderr,"╔════════════════════════════════════════════════════════════════════════╗\n");
  3041.   box_fprintf (stderr,"  Persistence of Vision Raytracer Ver %s%s",POV_RAY_VERSION,COMPILER_VER);
  3042.   box_fprintf (stderr,"    %s",DISTRIBUTION_MESSAGE_1);
  3043.   box_fprintf (stderr,"     %s",DISTRIBUTION_MESSAGE_2);
  3044.   box_fprintf (stderr,"     %s",DISTRIBUTION_MESSAGE_3);
  3045.   fprintf (stderr,"║  Copyright (c) 1993 POV-Team                                           ║\n");
  3046.   fprintf (stderr,"╟────────────────────────────────────────────────────────────────────────╢\n");
  3047.   fprintf (stderr,"║  POV-Ray is based on DKBTrace 2.12 by David K. Buck & Aaron A. Collins.║\n");
  3048.   fprintf (stderr,"║    Contributing Authors: (Alphabetically)                              ║\n");
  3049.   fprintf (stderr,"║      Steve Anger        Steve A. Bennett   David K. Buck               ║\n");
  3050.   fprintf (stderr,"║      Aaron A. Collins   Alexander Enzmann  Dan Farmer                  ║\n");
  3051.   fprintf (stderr,"║      Douglas Muir       Bill Pulver        Robert Skinner              ║\n");
  3052.   fprintf (stderr,"║      Scott Taylor       Drew Wells         Chris Young                 ║\n");
  3053.   fprintf (stderr,"║    Other contributors listed in the documentation.-                    ║\n");
  3054.   fprintf (stderr,"╚════════════════════════════════════════════════════════════════════════╝");
  3055.   fflush (stderr);
  3056.   }
  3057.  
  3058. /* Stats kept by the ray tracer: */
  3059. extern long Number_Of_Pixels, Number_Of_Rays, Number_Of_Pixels_Supersampled;
  3060. extern long Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded;
  3061. extern long Ray_Box_Tests, Ray_Box_Tests_Succeeded;
  3062. extern long Ray_Blob_Tests, Ray_Blob_Tests_Succeeded;
  3063. extern long Ray_Cone_Tests, Ray_Cone_Tests_Succeeded;
  3064. extern long Ray_Disc_Tests, Ray_Disc_Tests_Succeeded;
  3065. extern long Ray_Plane_Tests, Ray_Plane_Tests_Succeeded;
  3066. extern long Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded;
  3067. extern long Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded;
  3068. extern long Ray_Poly_Tests, Ray_Poly_Tests_Succeeded;
  3069. extern long Ray_Bicubic_Tests, Ray_Bicubic_Tests_Succeeded;
  3070. extern long Ray_Ht_Field_Tests, Ray_Ht_Field_Tests_Succeeded;
  3071. extern long Ray_Ht_Field_Box_Tests, Ray_HField_Box_Tests_Succeeded;
  3072. extern long Bounding_Region_Tests, Bounding_Region_Tests_Succeeded;
  3073. extern long Clipping_Region_Tests, Clipping_Region_Tests_Succeeded;
  3074. extern long Calls_To_Noise, Calls_To_DNoise;
  3075. extern long Shadow_Ray_Tests, Shadow_Rays_Succeeded, Shadow_Cache_Hits;
  3076. extern long Reflected_Rays_Traced, Refracted_Rays_Traced;
  3077. extern long Transmitted_Rays_Traced, Istack_overflows;
  3078. extern time_t tstart, tstop;
  3079. extern DBL tused;
  3080. extern FRAME Frame;
  3081.  
  3082. #ifdef DB_CODE
  3083. extern unsigned long nChecked, nEnqueued;
  3084. extern unsigned long Project_Tests, Project_Tests_Succeeded;
  3085. extern unsigned long totalQueues;
  3086. extern unsigned long totalQueueResets;
  3087. #endif
  3088.  
  3089. extern char Input_File_Name[FILE_NAME_LENGTH], Output_File_Name[FILE_NAME_LENGTH], Stat_File_Name[FILE_NAME_LENGTH];
  3090.  
  3091. void print_ibm_stats()
  3092.    {
  3093.    long hours,min;
  3094.    DBL sec;
  3095.    FILE *stat_out;
  3096.    long Pixels_In_Image;
  3097.  
  3098.    if (Options & VERBOSE_FILE)
  3099.       stat_out = fopen(Stat_File_Name,"w+t");
  3100.    else
  3101.     stat_out = stdout;
  3102.  
  3103.    Pixels_In_Image = (long)Frame.Screen_Width * (long)Frame.Screen_Height;
  3104.  
  3105.    fprintf (stat_out,"\n");
  3106.    fprintf (stat_out,"╔════════════════════════════════════════════════════════════════════════╗\n");
  3107.    box_fprintf (stat_out,"  Persistence of Vision Raytracer Ver %s%s",POV_RAY_VERSION, COMPILER_VER);
  3108.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  3109.    box_fprintf (stat_out,"  %s statistics",Input_File_Name);
  3110.    if(Pixels_In_Image > Number_Of_Pixels)
  3111.    box_fprintf (stat_out,"  Partial Image Rendered");
  3112.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  3113.    box_fprintf (stat_out," Image Resolution %d pixels wide x %d pixels high",Frame.Screen_Width, Frame.Screen_Height);
  3114.    box_fprintf (stat_out," # Rays Calculated     :  %10ld",Number_Of_Rays);
  3115.    box_fprintf (stat_out," # Pixels Calculated   :  %10ld", Number_Of_Pixels);
  3116.    box_fprintf (stat_out," # Pixels Supersampled :  %10ld",Number_Of_Pixels_Supersampled);
  3117.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  3118.    box_fprintf (stat_out,"   Ray -» Shape Intersection Tests");
  3119.    box_fprintf (stat_out,"   Type             Tests    Succeeded   Percentage");
  3120.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  3121.    if(Ray_Sphere_Tests)
  3122.    box_fprintf (stat_out,"  Sphere       %10ld  %10ld  %10.2f", Ray_Sphere_Tests, Ray_Sphere_Tests_Succeeded, ( ((DBL)Ray_Sphere_Tests_Succeeded/(DBL)Ray_Sphere_Tests) *100.0 ) );
  3123.    if(Ray_Plane_Tests)
  3124.    box_fprintf (stat_out,"  Plane        %10ld  %10ld  %10.2f", Ray_Plane_Tests, Ray_Plane_Tests_Succeeded, ( ((DBL)Ray_Plane_Tests_Succeeded/(DBL)Ray_Plane_Tests) *100.0 ));
  3125.    if(Ray_Triangle_Tests)
  3126.    box_fprintf (stat_out,"  Triangle     %10ld  %10ld  %10.2f", Ray_Triangle_Tests, Ray_Triangle_Tests_Succeeded, ( ((DBL)Ray_Triangle_Tests_Succeeded/(DBL)Ray_Triangle_Tests) *100.0 ));
  3127.    if(Ray_Quadric_Tests)
  3128.    box_fprintf (stat_out,"  Quadric      %10ld  %10ld  %10.2f", Ray_Quadric_Tests, Ray_Quadric_Tests_Succeeded, ( ((DBL)Ray_Quadric_Tests_Succeeded/(DBL)Ray_Quadric_Tests) *100.0 ));
  3129.    if(Ray_Blob_Tests)
  3130.    box_fprintf (stat_out,"  Blob         %10ld  %10ld  %10.2f", Ray_Blob_Tests, Ray_Blob_Tests_Succeeded, ( ((DBL)Ray_Blob_Tests_Succeeded/(DBL)Ray_Blob_Tests) *100.0 ));
  3131.    if(Ray_Box_Tests)
  3132.    box_fprintf (stat_out,"  Box          %10ld  %10ld  %10.2f", Ray_Box_Tests, Ray_Box_Tests_Succeeded, ( ((DBL)Ray_Box_Tests_Succeeded/(DBL)Ray_Box_Tests) *100.0 ));
  3133.    if(Ray_Cone_Tests)
  3134.    box_fprintf (stat_out,"  Cone\\Cyl.    %10ld  %10ld  %10.2f", Ray_Cone_Tests, Ray_Cone_Tests_Succeeded, ( ((DBL)Ray_Cone_Tests_Succeeded/(DBL)Ray_Cone_Tests) *100.0 ));
  3135.    if(Ray_Disc_Tests)
  3136.    box_fprintf (stat_out,"  Disc         %10ld  %10ld  %10.2f", Ray_Disc_Tests, Ray_Disc_Tests_Succeeded, ( ((DBL)Ray_Disc_Tests_Succeeded/(DBL)Ray_Disc_Tests) *100.0 ));
  3137.    if(Ray_Poly_Tests)
  3138.    box_fprintf (stat_out,"  Quartic\\Poly %10ld  %10ld  %10.2f", Ray_Poly_Tests, Ray_Poly_Tests_Succeeded, ( ((DBL)Ray_Poly_Tests_Succeeded/(DBL)Ray_Poly_Tests) *100.0 ));
  3139.    if(Ray_Bicubic_Tests)
  3140.    box_fprintf (stat_out,"  Bezier Patch %10ld  %10ld  %10.2f", Ray_Bicubic_Tests, Ray_Bicubic_Tests_Succeeded, ( ((DBL)Ray_Bicubic_Tests_Succeeded/(DBL)Ray_Bicubic_Tests) *100.0 ));
  3141.    if(Ray_Ht_Field_Tests)
  3142.    box_fprintf (stat_out,"  Height Fld   %10ld  %10ld  %10.2f", Ray_Ht_Field_Tests, Ray_Ht_Field_Tests_Succeeded, ( ((DBL)Ray_Ht_Field_Tests_Succeeded/(DBL)Ray_Ht_Field_Tests) *100.0 ));
  3143.    if(Ray_Ht_Field_Box_Tests)
  3144.    box_fprintf (stat_out,"  Hght Fld Box %10ld  %10ld  %10.2f", Ray_Ht_Field_Box_Tests, Ray_HField_Box_Tests_Succeeded, ( ((DBL)Ray_HField_Box_Tests_Succeeded/(DBL)Ray_Ht_Field_Box_Tests) *100.0 ));
  3145.    if(Bounding_Region_Tests)
  3146.    box_fprintf (stat_out,"  Bounds       %10ld  %10ld  %10.2f", Bounding_Region_Tests, Bounding_Region_Tests_Succeeded, ( ((DBL)Bounding_Region_Tests_Succeeded/(DBL)Bounding_Region_Tests) *100.0 ));
  3147.    if(Clipping_Region_Tests)
  3148.    box_fprintf (stat_out,"  Clips        %10ld  %10ld  %10.2f", Clipping_Region_Tests, Clipping_Region_Tests_Succeeded, ( ((DBL)Clipping_Region_Tests_Succeeded/(DBL)Clipping_Region_Tests) *100.0 ));
  3149. #ifdef DB_CODE
  3150.    box_fprintf (stat_out,"  Slabs        %10ld  %10ld  %10.2f", nChecked, nEnqueued, ( ((DBL)nEnqueued/(DBL)nChecked) *100.0 ));
  3151.    if(Project_Tests)
  3152.    box_fprintf (stat_out,"  Projections  %10ld  %10ld  %10.2f", Project_Tests, Project_Tests_Succeeded, ( ((DBL)Project_Tests_Succeeded/(DBL)Project_Tests) *100.0 ));
  3153. #endif
  3154.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  3155.    if(Calls_To_Noise)
  3156.    box_fprintf (stat_out,  "  Calls to Noise Routine  :  %10ld", Calls_To_Noise);
  3157.    if(Calls_To_DNoise)
  3158.    box_fprintf (stat_out,  "  Calls to DNoise Routine :  %10ld", Calls_To_DNoise);
  3159.    fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  3160.    if(Shadow_Ray_Tests){
  3161.      box_fprintf (stat_out,"  Shadow Ray Tests        :  %10ld",Shadow_Ray_Tests);
  3162. /* SJA */
  3163.      box_fprintf (stat_out,"  Shadow Cache Hits       :  %10ld",Shadow_Cache_Hits);
  3164. /* SJA */
  3165.      box_fprintf (stat_out,"  Blocking Objects Found  :  %10ld",Shadow_Rays_Succeeded);
  3166.      }
  3167.    if(Reflected_Rays_Traced)
  3168.    box_fprintf (stat_out,  "  Reflected Rays          :  %10ld", Reflected_Rays_Traced);
  3169.    if(Refracted_Rays_Traced)
  3170.    box_fprintf (stat_out,  "  Refracted Rays          :  %10ld", Refracted_Rays_Traced);
  3171.    if(Transmitted_Rays_Traced)
  3172.    box_fprintf (stat_out,  "  Transmitted Rays        :  %10ld", Transmitted_Rays_Traced);
  3173.    if(Istack_overflows)
  3174.    box_fprintf (stat_out,  "  I-Stack overflows       :  %10ld", Istack_overflows);
  3175.  
  3176.    if(tused==0) {
  3177.     STOP_TIME              /* Get trace done time. */
  3178.     tused = TIME_ELAPSED      /* Calc. elapsed time. Define TIME_ELAPSED as */
  3179.                   /* 0 in your specific CONFIG.H if unsupported */
  3180.     }
  3181.    if (tused != 0){
  3182.      /* Convert seconds to hours, min & sec. CdW */
  3183.      hours = (long) tused/3600;
  3184.      min = (long) (tused - hours*3600)/60;
  3185.      sec = tused - (DBL) (hours*3600 + min*60);
  3186.      fprintf (stat_out,"║────────────────────────────────────────────────────────────────────────║\n");
  3187. #ifdef DB_CODE
  3188.      box_fprintf (stat_out,"  Rendering Time          :   %5ld h %2d min %4.2f sec (%.2f sec)", hours,min,sec,tused);
  3189. #else
  3190.      box_fprintf (stat_out,"  Rendering Time          :   %5ld h %2d min %4.2f sec", hours,min,sec);
  3191. #endif
  3192.      }
  3193.      fprintf (stat_out,"╚════════════════════════════════════════════════════════════════════════╝\n");
  3194.  
  3195.     if (Options & VERBOSE_FILE)
  3196.       fclose(stat_out);
  3197.  
  3198. }
  3199.  
  3200.  
  3201. /* Output a string to stream with vfprintf formatted for ibm stat screen. */
  3202. /* String should be <80 chars              */
  3203. int _cdecl box_fprintf( FILE *stream, char *fmt , ... )
  3204. {
  3205.     va_list marker;
  3206.     char buffer[160];
  3207.     int len,i;
  3208.  
  3209.     buffer[0] = '║';
  3210.     va_start( marker, fmt );
  3211.     vsprintf( buffer+1, fmt, marker );
  3212.     va_end( marker );
  3213.     len = strlen (buffer);
  3214.     for(i=len;i<73;i++)
  3215.        buffer[i] = ' ';
  3216.     strcpy (buffer+73,"║\n");
  3217.     return( fputs(buffer,stream) );
  3218. }
  3219.  
  3220. /*
  3221.  * DJGCC's setvbuf() is totally screwed up.  Don't use it;
  3222.  * at least not until a later version than DJ 1.10/GCC 2.4.1.
  3223.  * Or if you want to live dangerously define SVBOK to say that
  3224.  * setvbuf is ok.
  3225.  */
  3226.  
  3227. #ifdef GCCDOS
  3228. #ifndef SVBOK
  3229. int setvbuf(file, buffer, mode, size)    /* replace theirs with ours */
  3230. FILE *file;
  3231. char *buffer;
  3232. int mode, size;
  3233. {
  3234.     return (0);     /* dummy up general success and return */
  3235. }
  3236. #endif
  3237. #endif
  3238.  
  3239.  
  3240.